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