1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights 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.dao.orm.QueryUtil;
29  import com.liferay.portal.kernel.log.Log;
30  import com.liferay.portal.kernel.log.LogFactoryUtil;
31  import com.liferay.portal.kernel.util.MapUtil;
32  import com.liferay.portal.kernel.util.ObjectValuePair;
33  import com.liferay.portal.kernel.util.PropsKeys;
34  import com.liferay.portal.kernel.util.StringPool;
35  import com.liferay.portal.kernel.xml.Document;
36  import com.liferay.portal.kernel.xml.Element;
37  import com.liferay.portal.kernel.xml.SAXReaderUtil;
38  import com.liferay.portal.lar.BasePortletDataHandler;
39  import com.liferay.portal.lar.PortletDataContext;
40  import com.liferay.portal.lar.PortletDataException;
41  import com.liferay.portal.lar.PortletDataHandlerBoolean;
42  import com.liferay.portal.lar.PortletDataHandlerControl;
43  import com.liferay.portal.lar.PortletDataHandlerKeys;
44  import com.liferay.portal.model.CompanyConstants;
45  import com.liferay.portal.service.ServiceContext;
46  import com.liferay.portal.util.PortletKeys;
47  import com.liferay.portal.util.PropsUtil;
48  import com.liferay.portlet.wiki.NoSuchNodeException;
49  import com.liferay.portlet.wiki.NoSuchPageException;
50  import com.liferay.portlet.wiki.model.WikiNode;
51  import com.liferay.portlet.wiki.model.WikiPage;
52  import com.liferay.portlet.wiki.service.WikiNodeLocalServiceUtil;
53  import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
54  import com.liferay.portlet.wiki.service.persistence.WikiNodeUtil;
55  import com.liferay.portlet.wiki.service.persistence.WikiPageUtil;
56  import com.liferay.portlet.wiki.util.comparator.PageCreateDateComparator;
57  
58  import java.util.ArrayList;
59  import java.util.List;
60  import java.util.Map;
61  
62  import javax.portlet.PortletPreferences;
63  
64  /**
65   * <a href="WikiPortletDataHandlerImpl.java.html"><b><i>View Source</i></b></a>
66   *
67   * @author Bruno Farache
68   * @author Jorge Ferrer
69   * @author Marcellus Tavares
70   */
71  public class WikiPortletDataHandlerImpl extends BasePortletDataHandler {
72  
73      public static void exportNode(
74              PortletDataContext context, Element nodesEl, Element pagesEl,
75              WikiNode node)
76          throws PortalException, SystemException {
77  
78          if (context.isWithinDateRange(node.getModifiedDate())) {
79              String path = getNodePath(context, node);
80  
81              if (context.isPathNotProcessed(path)) {
82                  Element nodeEl = nodesEl.addElement("node");
83  
84                  nodeEl.addAttribute("path", path);
85  
86                  node.setUserUuid(node.getUserUuid());
87  
88                  context.addZipEntry(path, node);
89              }
90          }
91  
92          List<WikiPage> nodePages = WikiPageUtil.findByNodeId(
93              node.getNodeId(), QueryUtil.ALL_POS, QueryUtil.ALL_POS,
94              new PageCreateDateComparator(true));
95  
96          for (WikiPage page : nodePages) {
97              exportPage(context, nodesEl, pagesEl, page);
98          }
99      }
100 
101     public static void importNode(
102             PortletDataContext context, Map<Long, Long> nodePKs, WikiNode node)
103         throws Exception {
104 
105         long userId = context.getUserId(node.getUserUuid());
106 
107         ServiceContext serviceContext = new ServiceContext();
108 
109         serviceContext.setAddCommunityPermissions(true);
110         serviceContext.setAddGuestPermissions(true);
111         serviceContext.setScopeGroupId(context.getGroupId());
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.getGroupId());
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.getGroupId(), 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());
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.getGroupId(), 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 
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 
191         WikiPage existingPage = null;
192 
193         try {
194             WikiNodeUtil.findByPrimaryKey(nodeId);
195 
196             if (context.getDataStrategy().equals(
197                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
198 
199                 try {
200                     existingPage = WikiPageUtil.findByUUID_G(
201                         page.getUuid(), context.getGroupId());
202                 }
203                 catch (NoSuchPageException nspe) {
204                 }
205 
206                 if (existingPage == null) {
207                     try {
208                         existingPage = WikiPageLocalServiceUtil.getPage(
209                             nodeId, page.getTitle());
210                     }
211                     catch (NoSuchPageException nspe) {
212                     }
213                 }
214 
215                 if (existingPage != null) {
216                     existingPage = WikiPageLocalServiceUtil.updatePage(
217                         userId, nodeId, existingPage.getTitle(), 0,
218                         page.getContent(), page.getSummary(), true,
219                         page.getFormat(), page.getParentTitle(),
220                         page.getRedirectTitle(), serviceContext);
221                 }
222                 else {
223                     existingPage = WikiPageLocalServiceUtil.addPage(
224                         page.getUuid(), userId, nodeId, page.getTitle(),
225                         page.getVersion(), page.getContent(), page.getSummary(),
226                         true, page.getFormat(), page.getHead(),
227                         page.getParentTitle(), page.getRedirectTitle(),
228                         serviceContext);
229                 }
230             }
231             else {
232                 existingPage = WikiPageLocalServiceUtil.addPage(
233                     null, userId, nodeId, page.getTitle(), page.getVersion(),
234                     page.getContent(), page.getSummary(), true,
235                     page.getFormat(), page.getHead(), page.getParentTitle(),
236                     page.getRedirectTitle(), serviceContext);
237             }
238 
239             if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
240                 page.isHead()) {
241 
242                 List<Element> attachmentEls = pageEl.elements("attachment");
243 
244                 List<ObjectValuePair<String, byte[]>> files =
245                     new ArrayList<ObjectValuePair<String, byte[]>>();
246 
247                 for (Element attachmentEl : attachmentEls) {
248                     String name = attachmentEl.attributeValue("name");
249                     String binPath = attachmentEl.attributeValue("bin-path");
250 
251                     byte[] bytes = context.getZipEntryAsByteArray(binPath);
252 
253                     files.add(new ObjectValuePair<String, byte[]>(name, bytes));
254                 }
255 
256                 if (files.size() > 0) {
257                     WikiPageLocalServiceUtil.addPageAttachments(
258                         nodeId, page.getTitle(), files);
259                 }
260             }
261 
262             if (context.getBooleanParameter(_NAMESPACE, "comments") &&
263                 page.isHead()) {
264 
265                 context.importComments(
266                     WikiPage.class, page.getResourcePrimKey(),
267                     existingPage.getResourcePrimKey(), context.getGroupId());
268             }
269 
270             if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
271                 context.importRatingsEntries(
272                     WikiPage.class, page.getResourcePrimKey(),
273                     existingPage.getResourcePrimKey());
274             }
275         }
276         catch (NoSuchNodeException nsne) {
277             _log.error("Could not find the node for page " + page.getPageId());
278         }
279     }
280 
281     public PortletPreferences deleteData(
282             PortletDataContext context, String portletId,
283             PortletPreferences preferences)
284         throws PortletDataException {
285 
286         try {
287             if (!context.addPrimaryKey(
288                     WikiPortletDataHandlerImpl.class, "deleteData")) {
289 
290                 WikiNodeLocalServiceUtil.deleteNodes(context.getGroupId());
291             }
292 
293             return null;
294         }
295         catch (Exception e) {
296             throw new PortletDataException(e);
297         }
298     }
299 
300     public String exportData(
301             PortletDataContext context, String portletId,
302             PortletPreferences preferences)
303         throws PortletDataException {
304 
305         try {
306             Document doc = SAXReaderUtil.createDocument();
307 
308             Element root = doc.addElement("wiki-data");
309 
310             root.addAttribute("group-id", String.valueOf(context.getGroupId()));
311 
312             Element nodesEl = root.addElement("nodes");
313             Element pagesEl = root.addElement("pages");
314 
315             List<WikiNode> nodes = WikiNodeUtil.findByGroupId(
316                 context.getGroupId());
317 
318             for (WikiNode node : nodes) {
319                 exportNode(context, nodesEl, pagesEl, node);
320             }
321 
322             return doc.formattedString();
323         }
324         catch (Exception e) {
325             throw new PortletDataException(e);
326         }
327     }
328 
329     public PortletDataHandlerControl[] getExportControls() {
330         return new PortletDataHandlerControl[] {
331             _nodesAndPages, _attachments, _categories, _comments, _tags
332         };
333     }
334 
335     public PortletDataHandlerControl[] getImportControls() {
336         return new PortletDataHandlerControl[] {
337             _nodesAndPages, _attachments, _categories, _comments, _tags
338         };
339     }
340 
341     public PortletPreferences importData(
342             PortletDataContext context, String portletId,
343             PortletPreferences preferences, String data)
344         throws PortletDataException {
345 
346         try {
347             Document doc = SAXReaderUtil.read(data);
348 
349             Element root = doc.getRootElement();
350 
351             List<Element> nodeEls = root.element("nodes").elements("node");
352 
353             Map<Long, Long> nodePKs =
354                 (Map<Long, Long>)context.getNewPrimaryKeysMap(WikiNode.class);
355 
356             for (Element nodeEl : nodeEls) {
357                 String path = nodeEl.attributeValue("path");
358 
359                 if (!context.isPathNotProcessed(path)) {
360                     continue;
361                 }
362 
363                 WikiNode node = (WikiNode)context.getZipEntryAsObject(path);
364 
365                 importNode(context, nodePKs, node);
366             }
367 
368             List<Element> pageEls = root.element("pages").elements("page");
369 
370             for (Element pageEl : pageEls) {
371                 String path = pageEl.attributeValue("path");
372 
373                 if (!context.isPathNotProcessed(path)) {
374                     continue;
375                 }
376 
377                 WikiPage page = (WikiPage)context.getZipEntryAsObject(path);
378 
379                 importPage(context, nodePKs, pageEl, page);
380             }
381 
382             return null;
383         }
384         catch (Exception e) {
385             throw new PortletDataException(e);
386         }
387     }
388 
389     protected static void exportNode(
390             PortletDataContext context, Element nodesEl, long nodeId)
391         throws PortalException, SystemException {
392 
393         if (!context.hasDateRange()) {
394             return;
395         }
396 
397         WikiNode node = WikiNodeUtil.findByPrimaryKey(nodeId);
398 
399         String path = getNodePath(context, node);
400 
401         if (!context.isPathNotProcessed(path)) {
402             return;
403         }
404 
405         Element nodeEl = nodesEl.addElement("node");
406 
407         nodeEl.addAttribute("path", path);
408 
409         node.setUserUuid(node.getUserUuid());
410 
411         context.addZipEntry(path, node);
412     }
413 
414     protected static void exportPage(
415             PortletDataContext context, Element nodesEl, Element pagesEl,
416             WikiPage page)
417         throws PortalException, SystemException {
418 
419         if (!context.isWithinDateRange(page.getModifiedDate())) {
420             return;
421         }
422 
423         String path = getPagePath(context, page);
424 
425         if (context.isPathNotProcessed(path)) {
426             Element pageEl = pagesEl.addElement("page");
427 
428             pageEl.addAttribute("path", path);
429 
430             page.setUserUuid(page.getUserUuid());
431 
432             if (context.getBooleanParameter(_NAMESPACE, "categories")) {
433                 context.addTagsCategories(
434                     WikiPage.class, page.getResourcePrimKey());
435             }
436 
437             if (context.getBooleanParameter(_NAMESPACE, "comments")) {
438                 context.addComments(WikiPage.class, page.getResourcePrimKey());
439             }
440 
441             if (context.getBooleanParameter(_NAMESPACE, "tags")) {
442                 context.addTagsEntries(
443                     WikiPage.class, page.getResourcePrimKey());
444             }
445 
446             if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
447                 page.isHead()) {
448 
449                 for (String attachment : page.getAttachmentsFiles()) {
450                     int pos = attachment.lastIndexOf(StringPool.SLASH);
451 
452                     String name = attachment.substring(pos + 1);
453                     String binPath = getPageAttachementBinPath(
454                         context, page, name);
455 
456                     Element attachmentEl = pageEl.addElement("attachment");
457 
458                     attachmentEl.addAttribute("name", name);
459                     attachmentEl.addAttribute("bin-path", binPath);
460 
461                     byte[] bytes = DLServiceUtil.getFile(
462                         context.getCompanyId(), CompanyConstants.SYSTEM,
463                         attachment);
464 
465                     context.addZipEntry(binPath, bytes);
466                 }
467 
468                 page.setAttachmentsDir(page.getAttachmentsDir());
469             }
470 
471             context.addZipEntry(path, page);
472         }
473 
474         exportNode(context, nodesEl, page.getNodeId());
475     }
476 
477     protected static String getNodePath(
478         PortletDataContext context, WikiNode node) {
479 
480         StringBuilder sb = new StringBuilder();
481 
482         sb.append(context.getPortletPath(PortletKeys.WIKI));
483         sb.append("/nodes/");
484         sb.append(node.getNodeId());
485         sb.append(".xml");
486 
487         return sb.toString();
488     }
489 
490     protected static String getPageAttachementBinPath(
491         PortletDataContext context, WikiPage page, String attachment) {
492 
493         StringBuilder sb = new StringBuilder();
494 
495         sb.append(context.getPortletPath(PortletKeys.WIKI));
496         sb.append("/bin/");
497         sb.append(page.getPageId());
498         sb.append(StringPool.SLASH);
499         sb.append(attachment);
500 
501         return sb.toString();
502     }
503 
504     protected static String getPagePath(
505         PortletDataContext context, WikiPage page) {
506 
507         StringBuilder sb = new StringBuilder();
508 
509         sb.append(context.getPortletPath(PortletKeys.WIKI));
510         sb.append("/pages/");
511         sb.append(page.getPageId());
512         sb.append(".xml");
513 
514         return sb.toString();
515     }
516 
517     private static final String _NAMESPACE = "wiki";
518 
519     private static final PortletDataHandlerBoolean _nodesAndPages =
520         new PortletDataHandlerBoolean(
521             _NAMESPACE, "wikis-and-pages", true, true);
522 
523     private static final PortletDataHandlerBoolean _attachments =
524         new PortletDataHandlerBoolean(_NAMESPACE, "attachments");
525 
526     private static final PortletDataHandlerBoolean _categories =
527         new PortletDataHandlerBoolean(_NAMESPACE, "categories");
528 
529     private static final PortletDataHandlerBoolean _comments =
530         new PortletDataHandlerBoolean(_NAMESPACE, "comments");
531 
532     private static final PortletDataHandlerBoolean _tags =
533         new PortletDataHandlerBoolean(_NAMESPACE, "tags");
534 
535     private static Log _log =
536         LogFactoryUtil.getLog(WikiPortletDataHandlerImpl.class);
537 
538 }