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