1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.wiki.lar;
24  
25  import com.liferay.documentlibrary.service.DLServiceUtil;
26  import com.liferay.portal.PortalException;
27  import com.liferay.portal.SystemException;
28  import com.liferay.portal.kernel.lar.PortletDataContext;
29  import com.liferay.portal.kernel.lar.PortletDataException;
30  import com.liferay.portal.kernel.lar.PortletDataHandler;
31  import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
32  import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
33  import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
34  import com.liferay.portal.kernel.util.ObjectValuePair;
35  import com.liferay.portal.kernel.util.StringPool;
36  import com.liferay.portal.model.CompanyConstants;
37  import com.liferay.portal.theme.ThemeDisplay;
38  import com.liferay.portal.util.DocumentUtil;
39  import com.liferay.portal.util.PortletKeys;
40  import com.liferay.portal.util.PropsKeys;
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.WikiPageFinderUtil;
50  import com.liferay.portlet.wiki.service.persistence.WikiPageUtil;
51  import com.liferay.util.MapUtil;
52  import com.liferay.util.xml.XMLFormatter;
53  
54  import java.rmi.RemoteException;
55  
56  import java.util.ArrayList;
57  import java.util.List;
58  import java.util.Map;
59  
60  import javax.portlet.PortletPreferences;
61  
62  import org.apache.commons.logging.Log;
63  import org.apache.commons.logging.LogFactory;
64  
65  import org.dom4j.Document;
66  import org.dom4j.DocumentHelper;
67  import org.dom4j.Element;
68  
69  /**
70   * <a href="WikiPortletDataHandlerImpl.java.html"><b><i>View Source</i></b></a>
71   *
72   * @author Bruno Farache
73   * @author Jorge Ferrer
74   *
75   */
76  public class WikiPortletDataHandlerImpl implements PortletDataHandler {
77  
78      public PortletPreferences deleteData(
79              PortletDataContext context, String portletId,
80              PortletPreferences prefs)
81          throws PortletDataException {
82  
83          try {
84              if (!context.addPrimaryKey(
85                      WikiPortletDataHandlerImpl.class, "deleteData")) {
86  
87                  WikiNodeLocalServiceUtil.deleteNodes(context.getGroupId());
88              }
89              return null;
90          }
91          catch (Exception e) {
92              throw new PortletDataException(e);
93          }
94      }
95  
96      public String exportData(
97              PortletDataContext context, String portletId,
98              PortletPreferences prefs)
99          throws PortletDataException {
100 
101         try {
102             Document doc = DocumentHelper.createDocument();
103 
104             Element root = doc.addElement("wiki-data");
105 
106             root.addAttribute("group-id", String.valueOf(context.getGroupId()));
107 
108             Element nodesEl = root.addElement("nodes");
109             Element pagesEl = root.addElement("pages");
110 
111             List<WikiNode> nodes = WikiNodeUtil.findByGroupId(
112                 context.getGroupId());
113 
114             for (WikiNode node : nodes) {
115                 exportNode(context, nodesEl, pagesEl, node);
116             }
117 
118             return XMLFormatter.toString(doc);
119         }
120         catch (Exception e) {
121             throw new PortletDataException(e);
122         }
123     }
124 
125     public PortletDataHandlerControl[] getExportControls() {
126         return new PortletDataHandlerControl[] {
127             _nodesAndPages, _attachments, _comments, _tags
128         };
129     }
130 
131     public PortletDataHandlerControl[] getImportControls() {
132         return new PortletDataHandlerControl[] {
133             _nodesAndPages, _attachments, _comments, _tags
134         };
135     }
136 
137     public PortletPreferences importData(
138             PortletDataContext context, String portletId,
139             PortletPreferences prefs, String data)
140         throws PortletDataException {
141 
142         try {
143             Document doc = DocumentUtil.readDocumentFromXML(data);
144 
145             Element root = doc.getRootElement();
146 
147             List<Element> nodeEls = root.element("nodes").elements("node");
148 
149             Map<Long, Long> nodePKs = context.getNewPrimaryKeysMap(
150                 WikiNode.class);
151 
152             for (Element nodeEl : nodeEls) {
153                 String path = nodeEl.attributeValue("path");
154 
155                 if (context.isPathNotProcessed(path)) {
156                     WikiNode node = (WikiNode)context.getZipEntryAsObject(path);
157 
158                     importNode(context, nodePKs, node);
159                 }
160             }
161 
162             List<Element> pageEls = root.element("pages").elements("page");
163 
164             for (Element pageEl : pageEls) {
165                 String path = pageEl.attributeValue("path");
166 
167                 if (context.isPathNotProcessed(path)) {
168                     WikiPage page = (WikiPage)context.getZipEntryAsObject(path);
169 
170                     importPage(context, nodePKs, pageEl, page);
171                 }
172             }
173 
174             return null;
175         }
176         catch (Exception e) {
177             throw new PortletDataException(e);
178         }
179     }
180 
181     public boolean isPublishToLiveByDefault() {
182         return false;
183     }
184 
185     protected void exportNode(
186             PortletDataContext context, Element nodesEl, Element pagesEl,
187             WikiNode node)
188         throws PortalException, SystemException {
189 
190         if (context.isWithinDateRange(node.getModifiedDate())) {
191             String path = getNodePath(context, node);
192 
193             Element nodeEl = nodesEl.addElement("node");
194 
195             nodeEl.addAttribute("path", path);
196 
197             if (context.isPathNotProcessed(path)) {
198                 node.setUserUuid(node.getUserUuid());
199 
200                 context.addZipEntry(path, node);
201             }
202         }
203 
204         List<WikiPage> nodePages = WikiPageUtil.findByNodeId(node.getNodeId());
205 
206         for (WikiPage page : nodePages) {
207             exportPage(context, nodesEl, pagesEl, page);
208         }
209     }
210 
211     protected void exportNode(
212             PortletDataContext context, Element nodesEl, long nodeId)
213         throws PortalException, SystemException {
214 
215         if (!context.hasDateRange()) {
216             return;
217         }
218 
219         WikiNode node = WikiNodeUtil.findByPrimaryKey(nodeId);
220 
221         String path = getNodePath(context, node);
222 
223         Element nodeEl = nodesEl.addElement("node");
224 
225         nodeEl.addAttribute("path", path);
226 
227         if (context.isPathNotProcessed(path)) {
228             node.setUserUuid(node.getUserUuid());
229 
230             context.addZipEntry(path, node);
231         }
232     }
233 
234     protected void exportPage(
235             PortletDataContext context, Element nodesEl, Element pagesEl,
236             WikiPage page)
237         throws PortalException, SystemException {
238 
239         if (!context.isWithinDateRange(page.getModifiedDate())) {
240             return;
241         }
242 
243         String path = getPagePath(context, page);
244 
245         Element pageEl = pagesEl.addElement("page");
246 
247         pageEl.addAttribute("path", path);
248 
249         if (context.isPathNotProcessed(path)) {
250             page.setUserUuid(page.getUserUuid());
251 
252             if (context.getBooleanParameter(_NAMESPACE, "comments")) {
253                 context.addComments(WikiPage.class, page.getResourcePrimKey());
254             }
255 
256             if (context.getBooleanParameter(_NAMESPACE, "tags")) {
257                 context.addTagsEntries(
258                     WikiPage.class, page.getResourcePrimKey());
259             }
260 
261             if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
262                 page.isHead()) {
263 
264                 for (String attachment : page.getAttachmentsFiles()) {
265                     int pos = attachment.lastIndexOf(StringPool.SLASH);
266 
267                     String name = attachment.substring(pos + 1);
268                     String binPath = getPageAttachementBinPath(
269                         context, page, name);
270 
271                     Element attachmentEl = pageEl.addElement("attachment");
272 
273                     attachmentEl.addAttribute("name", name);
274                     attachmentEl.addAttribute("bin-path", binPath);
275 
276                     try {
277                         byte[] bytes = DLServiceUtil.getFile(
278                             context.getCompanyId(), CompanyConstants.SYSTEM,
279                             attachment);
280 
281                         context.addZipEntry(binPath, bytes);
282                     }
283                     catch (RemoteException re) {
284                     }
285                 }
286 
287                 page.setAttachmentsDir(page.getAttachmentsDir());
288             }
289 
290             context.addZipEntry(path, page);
291         }
292 
293         exportNode(context, nodesEl, page.getNodeId());
294     }
295 
296     protected void importNode(
297             PortletDataContext context, Map<Long, Long> nodePKs, WikiNode node)
298         throws Exception {
299 
300         long userId = context.getUserId(node.getUserUuid());
301         long plid = context.getPlid();
302 
303         boolean addCommunityPermissions = true;
304         boolean addGuestPermissions = true;
305 
306         WikiNode existingNode = null;
307 
308         if (context.getDataStrategy().equals(
309                 PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
310 
311             existingNode = WikiNodeUtil.fetchByUUID_G(
312                 node.getUuid(), context.getGroupId());
313 
314             String nodeName = PropsUtil.get(PropsKeys.WIKI_INITIAL_NODE_NAME);
315 
316             if (existingNode == null && node.getName().equals(nodeName)) {
317                 try {
318                     WikiNodeUtil.removeByG_N(
319                         context.getGroupId(), node.getName());
320                 }
321                 catch (NoSuchNodeException nsne) {
322                 }
323             }
324 
325             if (existingNode == null) {
326                 existingNode = WikiNodeLocalServiceUtil.addNode(
327                     node.getUuid(), userId, plid, node.getName(),
328                     node.getDescription(), addCommunityPermissions,
329                     addGuestPermissions);
330             }
331             else {
332                 existingNode = WikiNodeLocalServiceUtil.updateNode(
333                     existingNode.getNodeId(), node.getName(),
334                     node.getDescription());
335             }
336         }
337         else {
338             String nodeName = PropsUtil.get(PropsKeys.WIKI_INITIAL_NODE_NAME);
339 
340             if (node.getName().equals(nodeName)) {
341                 try {
342                     WikiNodeUtil.removeByG_N(
343                         context.getGroupId(), node.getName());
344                 }
345                 catch (NoSuchNodeException nsne) {
346                 }
347             }
348 
349             existingNode = WikiNodeLocalServiceUtil.addNode(
350                 userId, plid, node.getName(), node.getDescription(),
351                 addCommunityPermissions, addGuestPermissions);
352         }
353 
354         nodePKs.put(node.getNodeId(), existingNode.getNodeId());
355     }
356 
357     protected void importPage(
358             PortletDataContext context, Map<Long, Long> nodePKs, Element pageEl,
359             WikiPage page)
360         throws Exception {
361 
362         long userId = context.getUserId(page.getUserUuid());
363         long nodeId = MapUtil.getLong(
364             nodePKs, page.getNodeId(), page.getNodeId());
365 
366         String[] tagsEntries = null;
367 
368         if (context.getBooleanParameter(_NAMESPACE, "tags")) {
369             tagsEntries = context.getTagsEntries(
370                 WikiPage.class, page.getResourcePrimKey());
371         }
372 
373         PortletPreferences prefs = null;
374 
375         ThemeDisplay themeDisplay = null;
376 
377         WikiPage existingPage = null;
378 
379         try {
380             WikiNodeUtil.findByPrimaryKey(nodeId);
381 
382             if (context.getDataStrategy().equals(
383                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
384 
385                 try {
386                     existingPage = WikiPageFinderUtil.findByUuid_G(
387                         page.getUuid(), context.getGroupId());
388 
389                     existingPage = WikiPageLocalServiceUtil.updatePage(
390                         userId, nodeId, existingPage.getTitle(), 0,
391                         page.getContent(), page.getSummary(), true,
392                         page.getFormat(), page.getParentTitle(),
393                         page.getRedirectTitle(), tagsEntries, prefs,
394                         themeDisplay);
395                 }
396                 catch (NoSuchPageException nspe) {
397                     existingPage = WikiPageLocalServiceUtil.addPage(
398                         page.getUuid(), userId, nodeId, page.getTitle(),
399                         page.getVersion(), page.getContent(), page.getSummary(),
400                         true, page.getFormat(), page.getHead(),
401                         page.getParentTitle(), page.getRedirectTitle(),
402                         tagsEntries, prefs, themeDisplay);
403                 }
404             }
405             else {
406                 existingPage = WikiPageLocalServiceUtil.addPage(
407                     null, userId, nodeId, page.getTitle(), page.getVersion(),
408                     page.getContent(), page.getSummary(), true,
409                     page.getFormat(), page.getHead(), page.getParentTitle(),
410                     page.getRedirectTitle(), tagsEntries, prefs, themeDisplay);
411             }
412 
413             if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
414                 page.isHead()) {
415 
416                 List<Element> attachmentEls = pageEl.elements("attachment");
417 
418                 List<ObjectValuePair<String, byte[]>> files =
419                     new ArrayList<ObjectValuePair<String, byte[]>>();
420 
421                 for (Element attachmentEl : attachmentEls) {
422                     String name = attachmentEl.attributeValue("name");
423                     String binPath = attachmentEl.attributeValue("bin-path");
424 
425                     byte[] bytes = context.getZipEntryAsByteArray(binPath);
426 
427                     files.add(new ObjectValuePair<String, byte[]>(name, bytes));
428                 }
429 
430                 if (files.size() > 0) {
431                     WikiPageLocalServiceUtil.addPageAttachments(
432                         nodeId, page.getTitle(), files);
433                 }
434             }
435 
436             if (context.getBooleanParameter(_NAMESPACE, "comments")) {
437                 context.importComments(
438                     WikiPage.class, page.getResourcePrimKey(),
439                     existingPage.getResourcePrimKey(), context.getGroupId());
440             }
441 
442             if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
443                 context.importRatingsEntries(
444                     WikiPage.class, page.getResourcePrimKey(),
445                     existingPage.getResourcePrimKey());
446             }
447         }
448         catch (NoSuchNodeException nsne) {
449             _log.error("Could not find the node for page " + page.getPageId());
450         }
451     }
452 
453     protected String getNodePath(PortletDataContext context, WikiNode node) {
454         StringBuilder sb = new StringBuilder();
455 
456         sb.append(context.getPortletPath(PortletKeys.WIKI));
457         sb.append("/nodes/");
458         sb.append(node.getNodeId());
459         sb.append(".xml");
460 
461         return sb.toString();
462     }
463 
464     protected String getPageAttachementBinPath(
465         PortletDataContext context, WikiPage page, String attachment) {
466 
467         StringBuilder sb = new StringBuilder();
468 
469         sb.append(context.getPortletPath(PortletKeys.WIKI));
470         sb.append("/bin/");
471         sb.append(page.getPageId());
472         sb.append(StringPool.SLASH);
473         sb.append(attachment);
474 
475         return sb.toString();
476     }
477 
478     protected String getPagePath(PortletDataContext context, WikiPage page) {
479         StringBuilder sb = new StringBuilder();
480 
481         sb.append(context.getPortletPath(PortletKeys.WIKI));
482         sb.append("/pages/");
483         sb.append(page.getPageId());
484         sb.append(".xml");
485 
486         return sb.toString();
487     }
488 
489     private static final String _NAMESPACE = "wiki";
490 
491     private static final PortletDataHandlerBoolean _nodesAndPages =
492         new PortletDataHandlerBoolean(
493             _NAMESPACE, "wikis-and-pages", true, true);
494 
495     private static final PortletDataHandlerBoolean _attachments =
496         new PortletDataHandlerBoolean(_NAMESPACE, "attachments");
497 
498     private static final PortletDataHandlerBoolean _comments =
499         new PortletDataHandlerBoolean(_NAMESPACE, "comments");
500 
501     private static final PortletDataHandlerBoolean _tags =
502         new PortletDataHandlerBoolean(_NAMESPACE, "tags");
503 
504     private static Log _log =
505         LogFactory.getLog(WikiPortletDataHandlerImpl.class);
506 
507 }