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.messageboards.lar;
24  
25  import com.liferay.documentlibrary.service.DLServiceUtil;
26  import com.liferay.portal.kernel.lar.PortletDataContext;
27  import com.liferay.portal.kernel.lar.PortletDataException;
28  import com.liferay.portal.kernel.lar.PortletDataHandler;
29  import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
30  import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
31  import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
32  import com.liferay.portal.kernel.util.ObjectValuePair;
33  import com.liferay.portal.model.CompanyConstants;
34  import com.liferay.portal.model.User;
35  import com.liferay.portal.service.persistence.UserUtil;
36  import com.liferay.portal.theme.ThemeDisplay;
37  import com.liferay.portal.util.DocumentUtil;
38  import com.liferay.portlet.messageboards.NoSuchCategoryException;
39  import com.liferay.portlet.messageboards.NoSuchMessageException;
40  import com.liferay.portlet.messageboards.NoSuchThreadException;
41  import com.liferay.portlet.messageboards.model.MBBan;
42  import com.liferay.portlet.messageboards.model.MBCategory;
43  import com.liferay.portlet.messageboards.model.MBMessage;
44  import com.liferay.portlet.messageboards.model.MBMessageFlag;
45  import com.liferay.portlet.messageboards.model.MBThread;
46  import com.liferay.portlet.messageboards.model.impl.MBCategoryImpl;
47  import com.liferay.portlet.messageboards.model.impl.MBMessageImpl;
48  import com.liferay.portlet.messageboards.service.MBBanLocalServiceUtil;
49  import com.liferay.portlet.messageboards.service.MBCategoryLocalServiceUtil;
50  import com.liferay.portlet.messageboards.service.MBMessageFlagLocalServiceUtil;
51  import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
52  import com.liferay.portlet.messageboards.service.persistence.MBBanUtil;
53  import com.liferay.portlet.messageboards.service.persistence.MBCategoryUtil;
54  import com.liferay.portlet.messageboards.service.persistence.MBMessageFinderUtil;
55  import com.liferay.portlet.messageboards.service.persistence.MBMessageFlagUtil;
56  import com.liferay.portlet.messageboards.service.persistence.MBMessageUtil;
57  import com.liferay.portlet.messageboards.service.persistence.MBThreadUtil;
58  import com.liferay.util.MapUtil;
59  
60  import com.thoughtworks.xstream.XStream;
61  
62  import java.util.ArrayList;
63  import java.util.Iterator;
64  import java.util.List;
65  import java.util.Map;
66  
67  import javax.portlet.PortletPreferences;
68  
69  import org.apache.commons.logging.Log;
70  import org.apache.commons.logging.LogFactory;
71  
72  import org.dom4j.Document;
73  import org.dom4j.DocumentHelper;
74  import org.dom4j.Element;
75  
76  /**
77   * <a href="MBPortletDataHandlerImpl.java.html"><b><i>View Source</i></b></a>
78   *
79   * @author Bruno Farache
80   *
81   */
82  public class MBPortletDataHandlerImpl implements PortletDataHandler {
83  
84      public PortletPreferences deleteData(
85              PortletDataContext context, String portletId,
86              PortletPreferences prefs)
87          throws PortletDataException {
88  
89          try {
90  
91              // Categories
92  
93              if (!context.addPrimaryKey(
94                      MBPortletDataHandlerImpl.class, "deleteData")) {
95  
96                  MBCategoryLocalServiceUtil.deleteCategories(
97                      context.getGroupId());
98              }
99  
100             return null;
101         }
102         catch (Exception e) {
103             throw new PortletDataException(e);
104         }
105     }
106 
107     public String exportData(
108             PortletDataContext context, String portletId,
109             PortletPreferences prefs)
110         throws PortletDataException {
111 
112         try {
113             XStream xStream = new XStream();
114 
115             Document doc = DocumentHelper.createDocument();
116 
117             Element root = doc.addElement("message-boards-data");
118 
119             root.addAttribute("group-id", String.valueOf(context.getGroupId()));
120 
121             // Categories
122 
123             List<MBCategory> categories = MBCategoryUtil.findByGroupId(
124                 context.getGroupId());
125 
126             List<MBMessage> messages = new ArrayList<MBMessage>();
127 
128             Iterator<MBCategory> categoriesItr = categories.iterator();
129 
130             while (categoriesItr.hasNext()) {
131                 MBCategory category = categoriesItr.next();
132 
133                 if (context.addPrimaryKey(
134                         MBCategory.class, category.getPrimaryKeyObj())) {
135 
136                     categoriesItr.remove();
137                 }
138                 else {
139                     category.setUserUuid(category.getUserUuid());
140 
141                     List<MBMessage> categoryMessages =
142                         MBMessageUtil.findByCategoryId(
143                             category.getCategoryId());
144 
145                     messages.addAll(categoryMessages);
146                 }
147             }
148 
149             String xml = xStream.toXML(categories);
150 
151             Element el = root.addElement("message-board-categories");
152 
153             Document tempDoc = DocumentUtil.readDocumentFromXML(xml);
154 
155             el.content().add(tempDoc.getRootElement().createCopy());
156 
157             // Messages
158 
159             List<MBMessageFlag> flags = new ArrayList<MBMessageFlag>();
160 
161             Iterator<MBMessage> messagesItr = messages.iterator();
162 
163             while (messagesItr.hasNext()) {
164                 MBMessage message = messagesItr.next();
165 
166                 if (context.addPrimaryKey(
167                         MBMessage.class, message.getPrimaryKeyObj())) {
168 
169                     messagesItr.remove();
170                 }
171                 else {
172                     message.setUserUuid(message.getUserUuid());
173                     message.setPriority(message.getPriority());
174 
175                     if (context.getBooleanParameter(_NAMESPACE, "tags")) {
176                         context.addTagsEntries(
177                             MBMessage.class, message.getPrimaryKeyObj());
178                     }
179 
180                     // Attachments
181 
182                     if (context.getBooleanParameter(
183                             _NAMESPACE, "attachments") &&
184                         message.isAttachments()) {
185 
186                         String[] attachments = message.getAttachmentsFiles();
187 
188                         for (int i = 0; i < attachments.length; i++) {
189                             String attachment = attachments[i];
190 
191                             byte[] byteArray = DLServiceUtil.getFile(
192                                 context.getCompanyId(), CompanyConstants.SYSTEM,
193                                 attachment);
194 
195                             context.getZipWriter().addEntry(
196                                 attachment, byteArray);
197                         }
198 
199                         message.setAttachmentsDir(message.getAttachmentsDir());
200                     }
201 
202                     if (context.getBooleanParameter(_NAMESPACE, "flags")) {
203                         List<MBMessageFlag> messageFlags =
204                             MBMessageFlagUtil.findByMessageId(
205                                 message.getMessageId());
206 
207                         flags.addAll(messageFlags);
208                     }
209                 }
210             }
211 
212             xml = xStream.toXML(messages);
213 
214             el = root.addElement("message-board-messages");
215 
216             tempDoc = DocumentUtil.readDocumentFromXML(xml);
217 
218             el.content().add(tempDoc.getRootElement().createCopy());
219 
220             // Flags
221 
222             Iterator<MBMessageFlag> flagsItr = flags.iterator();
223 
224             while (flagsItr.hasNext()) {
225                 MBMessageFlag flag = flagsItr.next();
226 
227                 if (context.addPrimaryKey(
228                         MBMessageFlag.class, flag.getPrimaryKeyObj())) {
229 
230                     flagsItr.remove();
231                 }
232                 else {
233                     flag.setUserUuid(flag.getUserUuid());
234                 }
235             }
236 
237             xml = xStream.toXML(flags);
238 
239             el = root.addElement("message-board-flags");
240 
241             tempDoc = DocumentUtil.readDocumentFromXML(xml);
242 
243             el.content().add(tempDoc.getRootElement().createCopy());
244 
245             // Bans
246 
247             List<MBBan> bans = new ArrayList<MBBan>();
248 
249             if (context.getBooleanParameter(_NAMESPACE, "user-bans")) {
250                 bans = MBBanUtil.findByGroupId(context.getGroupId());
251 
252                 Iterator<MBBan> bansItr = bans.iterator();
253 
254                 while (bansItr.hasNext()) {
255                     MBBan ban = bansItr.next();
256 
257                     if (context.addPrimaryKey(
258                             MBBan.class, ban.getPrimaryKeyObj())) {
259 
260                         bansItr.remove();
261                     }
262                     else {
263                         ban.setBanUserUuid(ban.getBanUserUuid());
264 
265                         ban.setUserUuid(ban.getUserUuid());
266                     }
267                 }
268             }
269 
270             xml = xStream.toXML(bans);
271 
272             el = root.addElement("message-board-bans");
273 
274             tempDoc = DocumentUtil.readDocumentFromXML(xml);
275 
276             el.content().add(tempDoc.getRootElement().createCopy());
277 
278             return doc.asXML();
279         }
280         catch (Exception e) {
281             throw new PortletDataException(e);
282         }
283     }
284 
285     public PortletDataHandlerControl[] getExportControls()
286         throws PortletDataException {
287 
288         return new PortletDataHandlerControl[] {
289             _categoriesAndMessages, _attachments, _userBans, _flags, _tags
290         };
291     }
292 
293     public PortletDataHandlerControl[] getImportControls()
294         throws PortletDataException {
295 
296         return new PortletDataHandlerControl[] {
297             _categoriesAndMessages, _attachments, _userBans, _flags, _tags
298         };
299     }
300 
301     public PortletPreferences importData(
302             PortletDataContext context, String portletId,
303             PortletPreferences prefs, String data)
304         throws PortletDataException {
305 
306         try {
307             XStream xStream = new XStream();
308 
309             Document doc = DocumentUtil.readDocumentFromXML(data);
310 
311             Element root = doc.getRootElement();
312 
313             // Categories
314 
315             Element el = root.element(
316                 "message-board-categories").element("list");
317 
318             Document tempDoc = DocumentHelper.createDocument();
319 
320             tempDoc.content().add(el.createCopy());
321 
322             Map<Long, Long> categoryPKs = context.getNewPrimaryKeysMap(
323                 MBCategory.class);
324 
325             List<MBCategory> categories = (List<MBCategory>)xStream.fromXML(
326                 tempDoc.asXML());
327 
328             for (MBCategory category : categories) {
329                 importCategory(context, categoryPKs, category);
330             }
331 
332             // Messages
333 
334             el = root.element("message-board-messages").element("list");
335 
336             tempDoc = DocumentHelper.createDocument();
337 
338             tempDoc.content().add(el.createCopy());
339 
340             Map<Long, Long> threadPKs = context.getNewPrimaryKeysMap(
341                 MBThread.class);
342             Map<Long, Long> messagePKs = context.getNewPrimaryKeysMap(
343                 MBMessage.class);
344 
345             List<MBMessage> messages = (List<MBMessage>)xStream.fromXML(
346                 tempDoc.asXML());
347 
348             for (MBMessage message : messages) {
349                 importMessage(
350                     context, categoryPKs, threadPKs, messagePKs, message);
351             }
352 
353             // Flags
354 
355             if (context.getBooleanParameter(_NAMESPACE, "flags")) {
356                 el = root.element("message-board-flags").element("list");
357 
358                 tempDoc = DocumentHelper.createDocument();
359 
360                 tempDoc.content().add(el.createCopy());
361 
362                 List<MBMessageFlag> flags =
363                     (List<MBMessageFlag>)xStream.fromXML(tempDoc.asXML());
364 
365                 for (MBMessageFlag flag : flags) {
366                     importFlag(context, messagePKs, flag);
367                 }
368             }
369 
370             // Bans
371 
372             if (context.getBooleanParameter(_NAMESPACE, "user-bans")) {
373                 el = root.element("message-board-bans").element("list");
374 
375                 tempDoc = DocumentHelper.createDocument();
376 
377                 tempDoc.content().add(el.createCopy());
378 
379                 List<MBBan> bans = (List<MBBan>)xStream.fromXML(
380                     tempDoc.asXML());
381 
382                 for (MBBan ban : bans) {
383                     importBan(context, ban);
384                 }
385             }
386 
387             return null;
388         }
389         catch (Exception e) {
390             throw new PortletDataException(e);
391         }
392     }
393 
394     public boolean isPublishToLiveByDefault() {
395         return false;
396     }
397 
398     protected void importBan(PortletDataContext context, MBBan ban)
399         throws Exception {
400 
401         long userId = context.getUserId(ban.getUserUuid());
402         long plid = context.getPlid();
403 
404         List<User> users = UserUtil.findByUuid(ban.getBanUserUuid());
405 
406         Iterator<User> itr = users.iterator();
407 
408         if (itr.hasNext()) {
409             User user = itr.next();
410 
411             MBBanLocalServiceUtil.addBan(userId, plid, user.getUserId());
412         }
413         else {
414             _log.error(
415                 "Could not find banned user with uuid " + ban.getBanUserUuid());
416         }
417     }
418 
419     protected void importCategory(
420             PortletDataContext context, Map<Long, Long> categoryPKs,
421             MBCategory category)
422         throws Exception {
423 
424         long userId = context.getUserId(category.getUserUuid());
425         long plid = context.getPlid();
426         long parentCategoryId = MapUtil.getLong(
427             categoryPKs, category.getParentCategoryId(),
428             category.getParentCategoryId());
429 
430         boolean addCommunityPermissions = true;
431         boolean addGuestPermissions = true;
432 
433         MBCategory existingCategory = null;
434 
435         try {
436             if (parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) {
437                 MBCategoryUtil.findByPrimaryKey(parentCategoryId);
438             }
439 
440             if (context.getDataStrategy().equals(
441                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
442 
443                 existingCategory = MBCategoryUtil.fetchByUUID_G(
444                     category.getUuid(), context.getGroupId());
445 
446                 if (existingCategory == null) {
447                     existingCategory = MBCategoryLocalServiceUtil.addCategory(
448                         category.getUuid(), userId, plid, parentCategoryId,
449                         category.getName(), category.getDescription(),
450                         addCommunityPermissions, addGuestPermissions);
451                 }
452                 else {
453                     existingCategory =
454                         MBCategoryLocalServiceUtil.updateCategory(
455                             existingCategory.getCategoryId(), parentCategoryId,
456                             category.getName(), category.getDescription(),
457                             false);
458                 }
459             }
460             else {
461                 existingCategory = MBCategoryLocalServiceUtil.addCategory(
462                     userId, plid, parentCategoryId, category.getName(),
463                     category.getDescription(), addCommunityPermissions,
464                     addGuestPermissions);
465             }
466 
467             categoryPKs.put(
468                 category.getCategoryId(), existingCategory.getCategoryId());
469         }
470         catch (NoSuchCategoryException nsce) {
471             _log.error(
472                 "Could not find the parent category for category " +
473                     category.getCategoryId());
474         }
475     }
476 
477     protected void importFlag(
478             PortletDataContext context, Map<Long, Long> messagePKs,
479             MBMessageFlag flag)
480         throws Exception {
481 
482         long userId = context.getUserId(flag.getUserUuid());
483         long messageId = MapUtil.getLong(
484             messagePKs, flag.getMessageId(), flag.getMessageId());
485 
486         try {
487             List<MBMessage> messages = new ArrayList<MBMessage>();
488 
489             messages.add(MBMessageUtil.findByPrimaryKey(messageId));
490 
491             MBMessageFlagLocalServiceUtil.addReadFlags(userId, messages);
492         }
493         catch (NoSuchMessageException nsme) {
494             _log.error(
495                 "Could not find the message for flag " +
496                     flag.getMessageFlagId());
497         }
498     }
499 
500     protected void importMessage(
501             PortletDataContext context, Map<Long, Long> categoryPKs,
502             Map<Long, Long> threadPKs, Map<Long, Long> messagePKs,
503             MBMessage message)
504         throws Exception {
505 
506         long userId = context.getUserId(message.getUserUuid());
507         long categoryId = MapUtil.getLong(
508             categoryPKs, message.getCategoryId(), message.getCategoryId());
509         long threadId = MapUtil.getLong(
510             threadPKs, message.getThreadId(), message.getThreadId());
511         long parentMessageId = MapUtil.getLong(
512             messagePKs, message.getParentMessageId(),
513             message.getParentMessageId());
514 
515         List<ObjectValuePair<String, byte[]>> files =
516             new ArrayList<ObjectValuePair<String, byte[]>>();
517         List<String> existingFiles = new ArrayList<String>();
518 
519         if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
520             message.isAttachments()) {
521 
522             files = context.getZipReader().getFolderEntries().get(
523                 message.getAttachmentsDir() + "/");
524 
525             if (files == null) {
526                 _log.error(
527                     "Could not find attachments for message " +
528                         message.getMessageId());
529 
530                 files = new ArrayList<ObjectValuePair<String, byte[]>>();
531             }
532         }
533 
534         String[] tagsEntries = null;
535 
536         if (context.getBooleanParameter(_NAMESPACE, "tags")) {
537             tagsEntries = context.getTagsEntries(
538                 MBMessage.class, message.getPrimaryKeyObj());
539         }
540 
541         PortletPreferences prefs = null;
542 
543         boolean addCommunityPermissions = true;
544         boolean addGuestPermissions = true;
545 
546         ThemeDisplay themeDisplay = null;
547 
548         MBMessage existingMessage = null;
549 
550         try {
551             MBCategoryUtil.findByPrimaryKey(categoryId);
552 
553             if (parentMessageId != MBMessageImpl.DEFAULT_PARENT_MESSAGE_ID) {
554                 MBMessageUtil.findByPrimaryKey(parentMessageId);
555                 MBThreadUtil.findByPrimaryKey(threadId);
556             }
557 
558             if (context.getDataStrategy().equals(
559                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
560 
561                 try {
562                     existingMessage = MBMessageFinderUtil.findByUuid_G(
563                         message.getUuid(), context.getGroupId());
564 
565                     MBMessageLocalServiceUtil.updateMessage(
566                         userId, existingMessage.getMessageId(),
567                         message.getSubject(), message.getBody(), files,
568                         existingFiles, message.getPriority(), tagsEntries,
569                         prefs, themeDisplay);
570                 }
571                 catch (NoSuchMessageException nsme) {
572                     existingMessage = MBMessageLocalServiceUtil.addMessage(
573                         message.getUuid(), userId, categoryId, threadId,
574                         parentMessageId, message.getSubject(),
575                         message.getBody(), files, message.getAnonymous(),
576                         message.getPriority(), tagsEntries, prefs,
577                         addCommunityPermissions, addGuestPermissions,
578                         themeDisplay);
579                 }
580             }
581             else {
582                 existingMessage = MBMessageLocalServiceUtil.addMessage(
583                     userId, categoryId, threadId, parentMessageId,
584                     message.getSubject(), message.getBody(), files,
585                     message.getAnonymous(), message.getPriority(), tagsEntries,
586                     prefs, addCommunityPermissions, addGuestPermissions,
587                     themeDisplay);
588             }
589 
590             threadPKs.put(
591                 new Long(message.getThreadId()),
592                 new Long(existingMessage.getThreadId()));
593             messagePKs.put(
594                 message.getMessageId(), existingMessage.getMessageId());
595         }
596         catch (NoSuchCategoryException nsce) {
597             _log.error(
598                 "Could not find the parent category for message " +
599                     message.getMessageId());
600         }
601         catch (NoSuchMessageException nsme) {
602             _log.error(
603                 "Could not find the parent message for message " +
604                     message.getMessageId());
605         }
606         catch (NoSuchThreadException nste) {
607             _log.error(
608                 "Could not find the thread for message " +
609                     message.getMessageId());
610         }
611     }
612 
613     private static final String _NAMESPACE = "message_board";
614 
615     private static final PortletDataHandlerBoolean _categoriesAndMessages =
616         new PortletDataHandlerBoolean(
617             _NAMESPACE, "categories-and-messages", true, true);
618 
619     private static final PortletDataHandlerBoolean _attachments =
620         new PortletDataHandlerBoolean(_NAMESPACE, "attachments");
621 
622     private static final PortletDataHandlerBoolean _userBans =
623         new PortletDataHandlerBoolean(_NAMESPACE, "user-bans");
624 
625     private static final PortletDataHandlerBoolean _flags =
626         new PortletDataHandlerBoolean(_NAMESPACE, "flags");
627 
628     private static final PortletDataHandlerBoolean _tags =
629         new PortletDataHandlerBoolean(_NAMESPACE, "tags");
630 
631     private static Log _log =
632         LogFactory.getLog(MBPortletDataHandlerImpl.class);
633 
634 }