1
22
23 package com.liferay.portlet.messageboards.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.model.User;
38 import com.liferay.portal.service.persistence.UserUtil;
39 import com.liferay.portal.theme.ThemeDisplay;
40 import com.liferay.portal.util.DocumentUtil;
41 import com.liferay.portal.util.PortletKeys;
42 import com.liferay.portlet.messageboards.NoSuchCategoryException;
43 import com.liferay.portlet.messageboards.NoSuchMessageException;
44 import com.liferay.portlet.messageboards.NoSuchThreadException;
45 import com.liferay.portlet.messageboards.model.MBBan;
46 import com.liferay.portlet.messageboards.model.MBCategory;
47 import com.liferay.portlet.messageboards.model.MBMessage;
48 import com.liferay.portlet.messageboards.model.MBMessageFlag;
49 import com.liferay.portlet.messageboards.model.MBThread;
50 import com.liferay.portlet.messageboards.model.impl.MBCategoryImpl;
51 import com.liferay.portlet.messageboards.model.impl.MBMessageImpl;
52 import com.liferay.portlet.messageboards.service.MBBanLocalServiceUtil;
53 import com.liferay.portlet.messageboards.service.MBCategoryLocalServiceUtil;
54 import com.liferay.portlet.messageboards.service.MBMessageFlagLocalServiceUtil;
55 import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
56 import com.liferay.portlet.messageboards.service.persistence.MBBanUtil;
57 import com.liferay.portlet.messageboards.service.persistence.MBCategoryUtil;
58 import com.liferay.portlet.messageboards.service.persistence.MBMessageFinderUtil;
59 import com.liferay.portlet.messageboards.service.persistence.MBMessageFlagUtil;
60 import com.liferay.portlet.messageboards.service.persistence.MBMessageUtil;
61 import com.liferay.portlet.messageboards.service.persistence.MBThreadUtil;
62 import com.liferay.util.MapUtil;
63 import com.liferay.util.xml.XMLFormatter;
64
65 import java.rmi.RemoteException;
66
67 import java.util.ArrayList;
68 import java.util.Iterator;
69 import java.util.List;
70 import java.util.Map;
71
72 import javax.portlet.PortletPreferences;
73
74 import org.apache.commons.logging.Log;
75 import org.apache.commons.logging.LogFactory;
76
77 import org.dom4j.Document;
78 import org.dom4j.DocumentHelper;
79 import org.dom4j.Element;
80
81
88 public class MBPortletDataHandlerImpl implements PortletDataHandler {
89
90 public PortletPreferences deleteData(
91 PortletDataContext context, String portletId,
92 PortletPreferences prefs)
93 throws PortletDataException {
94
95 try {
96 if (!context.addPrimaryKey(
97 MBPortletDataHandlerImpl.class, "deleteData")) {
98
99 MBCategoryLocalServiceUtil.deleteCategories(
100 context.getGroupId());
101 }
102
103 return null;
104 }
105 catch (Exception e) {
106 throw new PortletDataException(e);
107 }
108 }
109
110 public String exportData(
111 PortletDataContext context, String portletId,
112 PortletPreferences prefs)
113 throws PortletDataException {
114
115 try {
116 Document doc = DocumentHelper.createDocument();
117
118 Element root = doc.addElement("message-boards-data");
119
120 root.addAttribute("group-id", String.valueOf(context.getGroupId()));
121
122 Element categoriesEl = root.addElement("categories");
123 Element messagesEl = root.addElement("messages");
124 Element messageFlagsEl = root.addElement("message-flags");
125 Element userBansEl = root.addElement("user-bans");
126
127 List<MBCategory> categories = MBCategoryUtil.findByGroupId(
128 context.getGroupId());
129
130 for (MBCategory category : categories) {
131 exportCategory(
132 context, categoriesEl, messagesEl, messageFlagsEl,
133 category);
134 }
135
136 if (context.getBooleanParameter(_NAMESPACE, "user-bans")) {
137 List<MBBan> bans = MBBanUtil.findByGroupId(
138 context.getGroupId());
139
140 for (MBBan ban : bans) {
141 exportUserBan(context, userBansEl, ban);
142 }
143 }
144
145 return XMLFormatter.toString(doc);
146 }
147 catch (Exception e) {
148 throw new PortletDataException(e);
149 }
150 }
151
152 public PortletDataHandlerControl[] getExportControls() {
153 return new PortletDataHandlerControl[] {
154 _categoriesAndMessages, _attachments, _userBans, _flags, _ratings,
155 _tags
156 };
157 }
158
159 public PortletDataHandlerControl[] getImportControls() {
160 return new PortletDataHandlerControl[] {
161 _categoriesAndMessages, _attachments, _userBans, _flags, _ratings,
162 _tags
163 };
164 }
165
166 public PortletPreferences importData(
167 PortletDataContext context, String portletId,
168 PortletPreferences prefs, String data)
169 throws PortletDataException {
170
171 try {
172 Document doc = DocumentUtil.readDocumentFromXML(data);
173
174 Element root = doc.getRootElement();
175
176 List<Element> categoryEls = root.element("categories").elements(
177 "category");
178
179 Map<Long, Long> categoryPKs = context.getNewPrimaryKeysMap(
180 MBCategory.class);
181
182 for (Element categoryEl : categoryEls) {
183 String path = categoryEl.attributeValue("path");
184
185 if (context.isPathNotProcessed(path)) {
186 MBCategory category =
187 (MBCategory)context.getZipEntryAsObject(path);
188
189 importCategory(context, categoryPKs, category);
190 }
191 }
192
193 List<Element> messageEls = root.element("messages").elements(
194 "message");
195
196 Map<Long, Long> threadPKs = context.getNewPrimaryKeysMap(
197 MBThread.class);
198 Map<Long, Long> messagePKs = context.getNewPrimaryKeysMap(
199 MBMessage.class);
200
201 for (Element messageEl : messageEls) {
202 String path = messageEl.attributeValue("path");
203
204 if (context.isPathNotProcessed(path)) {
205 MBMessage message = (MBMessage)context.getZipEntryAsObject(
206 path);
207
208 importMessage(
209 context, categoryPKs, threadPKs, messagePKs, messageEl,
210 message);
211 }
212 }
213
214 if (context.getBooleanParameter(_NAMESPACE, "flags")) {
215 List<Element> flagEls = root.element("message-flags").elements(
216 "flag");
217
218 for (Element flagEl : flagEls) {
219 String path = flagEl.attributeValue("path");
220
221 if (context.isPathNotProcessed(path)) {
222 MBMessageFlag flag =
223 (MBMessageFlag)context.getZipEntryAsObject(path);
224
225 importFlag(context, messagePKs, flag);
226 }
227 }
228 }
229
230 if (context.getBooleanParameter(_NAMESPACE, "user-bans")) {
231 List<Element> banEls = root.element("user-bans").elements(
232 "user-ban");
233
234 for (Element banEl : banEls) {
235 String path = banEl.attributeValue("path");
236
237 if (context.isPathNotProcessed(path)) {
238 MBBan ban = (MBBan)context.getZipEntryAsObject(path);
239
240 importBan(context, ban);
241 }
242 }
243 }
244
245 return null;
246 }
247 catch (Exception e) {
248 throw new PortletDataException(e);
249 }
250 }
251
252 public boolean isPublishToLiveByDefault() {
253 return false;
254 }
255
256 protected void exportCategory(
257 PortletDataContext context, Element categoriesEl,
258 Element messagesEl, Element messageFlagsEl, MBCategory category)
259 throws PortalException, SystemException {
260
261 if (context.isWithinDateRange(category.getModifiedDate())) {
262 String path = getCategoryPath(context, category);
263
264 Element categoryEl = categoriesEl.addElement("category");
265
266 categoryEl.addAttribute("path", path);
267
268 if (context.isPathNotProcessed(path)) {
269 category.setUserUuid(category.getUserUuid());
270
271 context.addZipEntry(path, category);
272 }
273
274 exportParentCategory(
275 context, categoriesEl, category.getParentCategoryId());
276 }
277
278 List<MBMessage> messages = MBMessageUtil.findByCategoryId(
279 category.getCategoryId());
280
281 for (MBMessage message : messages) {
282 exportMessage(
283 context, categoriesEl, messagesEl, messageFlagsEl, message);
284 }
285 }
286
287 protected void exportMessage(
288 PortletDataContext context, Element categoriesEl,
289 Element messagesEl, Element messageFlagsEl, MBMessage message)
290 throws PortalException, SystemException {
291
292 if (!context.isWithinDateRange(message.getModifiedDate())) {
293 return;
294 }
295
296 String path = getMessagePath(context, message);
297
298 Element messageEl = messagesEl.addElement("message");
299
300 messageEl.addAttribute("path", path);
301
302 if (context.isPathNotProcessed(path)) {
303 message.setUserUuid(message.getUserUuid());
304 message.setPriority(message.getPriority());
305
306 if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
307 context.addRatingsEntries(
308 MBMessage.class, message.getMessageId());
309 }
310
311 if (context.getBooleanParameter(_NAMESPACE, "tags")) {
312 context.addTagsEntries(
313 MBMessage.class, message.getMessageId());
314 }
315
316 if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
317 message.isAttachments()) {
318
319 for (String attachment : message.getAttachmentsFiles()) {
320 int pos = attachment.lastIndexOf(StringPool.FORWARD_SLASH);
321
322 String name = attachment.substring(pos + 1);
323 String binPath = getMessageAttachementBinPath(
324 context, message, name);
325
326 Element attachmentEl = messageEl.addElement("attachment");
327
328 attachmentEl.addAttribute("name", name);
329 attachmentEl.addAttribute("bin-path", binPath);
330
331 try {
332 byte[] bytes = DLServiceUtil.getFile(
333 context.getCompanyId(), CompanyConstants.SYSTEM,
334 attachment);
335
336 context.addZipEntry(binPath, bytes);
337 }
338 catch (RemoteException re) {
339 }
340 }
341
342 message.setAttachmentsDir(message.getAttachmentsDir());
343 }
344
345 if (context.getBooleanParameter(_NAMESPACE, "flags")) {
346 List<MBMessageFlag> messageFlags =
347 MBMessageFlagUtil.findByMessageId(
348 message.getMessageId());
349
350 for (MBMessageFlag messageFlag : messageFlags) {
351 exportMessageFlag(context, messageFlagsEl, messageFlag);
352 }
353 }
354
355 context.addZipEntry(path, message);
356 }
357
358 exportParentCategory(context, categoriesEl, message.getCategoryId());
359 }
360
361 protected void exportMessageFlag(
362 PortletDataContext context, Element messageFlagsEl,
363 MBMessageFlag messageFlag)
364 throws SystemException {
365
366 String path = getMessageFlagPath(context, messageFlag);
367
368 Element messageFlagEl = messageFlagsEl.addElement("message-flag");
369
370 messageFlagEl.addAttribute("path", path);
371
372 if (context.isPathNotProcessed(path)) {
373 messageFlag.setUserUuid(messageFlag.getUserUuid());
374
375 context.addZipEntry(path, messageFlag);
376 }
377 }
378
379 protected void exportParentCategory(
380 PortletDataContext context, Element categoriesEl, long categoryId)
381 throws PortalException, SystemException {
382
383 if ((!context.hasDateRange()) ||
384 (categoryId == MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID)) {
385
386 return;
387 }
388
389 MBCategory category = MBCategoryUtil.findByPrimaryKey(categoryId);
390
391 String path = getCategoryPath(context, category);
392
393 Element categoryEl = categoriesEl.addElement("category");
394
395 categoryEl.addAttribute("path", path);
396
397 if (context.isPathNotProcessed(path)) {
398 category.setUserUuid(category.getUserUuid());
399
400 context.addZipEntry(path, category);
401 }
402
403 exportParentCategory(
404 context, categoriesEl, category.getParentCategoryId());
405 }
406
407 protected void exportUserBan(
408 PortletDataContext context, Element userBansEl, MBBan ban)
409 throws SystemException {
410
411 if (!context.isWithinDateRange(ban.getModifiedDate())) {
412 return;
413 }
414
415 String path = getUserBanPath(context, ban);
416
417 Element userBanEl = userBansEl.addElement("user-ban");
418
419 userBanEl.addAttribute("path", path);
420
421 if (context.isPathNotProcessed(path)) {
422 ban.setBanUserUuid(ban.getBanUserUuid());
423 ban.setUserUuid(ban.getUserUuid());
424
425 context.addZipEntry(path, ban);
426 }
427 }
428
429 protected void importBan(PortletDataContext context, MBBan ban)
430 throws Exception {
431
432 long userId = context.getUserId(ban.getUserUuid());
433 long plid = context.getPlid();
434
435 List<User> users = UserUtil.findByUuid(ban.getBanUserUuid());
436
437 Iterator<User> itr = users.iterator();
438
439 if (itr.hasNext()) {
440 User user = itr.next();
441
442 MBBanLocalServiceUtil.addBan(userId, plid, user.getUserId());
443 }
444 else {
445 _log.error(
446 "Could not find banned user with uuid " + ban.getBanUserUuid());
447 }
448 }
449
450 protected void importCategory(
451 PortletDataContext context, Map<Long, Long> categoryPKs,
452 MBCategory category)
453 throws Exception {
454
455 long userId = context.getUserId(category.getUserUuid());
456 long plid = context.getPlid();
457 long parentCategoryId = MapUtil.getLong(
458 categoryPKs, category.getParentCategoryId(),
459 category.getParentCategoryId());
460
461 boolean addCommunityPermissions = true;
462 boolean addGuestPermissions = true;
463
464 MBCategory existingCategory = null;
465
466 try {
467 if (parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) {
468 MBCategoryUtil.findByPrimaryKey(parentCategoryId);
469 }
470
471 if (context.getDataStrategy().equals(
472 PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
473
474 existingCategory = MBCategoryUtil.fetchByUUID_G(
475 category.getUuid(), context.getGroupId());
476
477 if (existingCategory == null) {
478 existingCategory = MBCategoryLocalServiceUtil.addCategory(
479 category.getUuid(), userId, plid, parentCategoryId,
480 category.getName(), category.getDescription(),
481 addCommunityPermissions, addGuestPermissions);
482 }
483 else {
484 existingCategory =
485 MBCategoryLocalServiceUtil.updateCategory(
486 existingCategory.getCategoryId(), parentCategoryId,
487 category.getName(), category.getDescription(),
488 false);
489 }
490 }
491 else {
492 existingCategory = MBCategoryLocalServiceUtil.addCategory(
493 userId, plid, parentCategoryId, category.getName(),
494 category.getDescription(), addCommunityPermissions,
495 addGuestPermissions);
496 }
497
498 categoryPKs.put(
499 category.getCategoryId(), existingCategory.getCategoryId());
500 }
501 catch (NoSuchCategoryException nsce) {
502 _log.error(
503 "Could not find the parent category for category " +
504 category.getCategoryId());
505 }
506 }
507
508 protected void importFlag(
509 PortletDataContext context, Map<Long, Long> messagePKs,
510 MBMessageFlag flag)
511 throws Exception {
512
513 long userId = context.getUserId(flag.getUserUuid());
514 long messageId = MapUtil.getLong(
515 messagePKs, flag.getMessageId(), flag.getMessageId());
516
517 try {
518 List<MBMessage> messages = new ArrayList<MBMessage>();
519
520 messages.add(MBMessageUtil.findByPrimaryKey(messageId));
521
522 MBMessageFlagLocalServiceUtil.addReadFlags(userId, messages);
523 }
524 catch (NoSuchMessageException nsme) {
525 _log.error(
526 "Could not find the message for flag " +
527 flag.getMessageFlagId());
528 }
529 }
530
531 protected void importMessage(
532 PortletDataContext context, Map<Long, Long> categoryPKs,
533 Map<Long, Long> threadPKs, Map<Long, Long> messagePKs,
534 Element messageEl, MBMessage message)
535 throws Exception {
536
537 long userId = context.getUserId(message.getUserUuid());
538 String userName = message.getUserName();
539 long categoryId = MapUtil.getLong(
540 categoryPKs, message.getCategoryId(), message.getCategoryId());
541 long threadId = MapUtil.getLong(
542 threadPKs, message.getThreadId(), message.getThreadId());
543 long parentMessageId = MapUtil.getLong(
544 messagePKs, message.getParentMessageId(),
545 message.getParentMessageId());
546
547 List<ObjectValuePair<String, byte[]>> files =
548 new ArrayList<ObjectValuePair<String, byte[]>>();
549 List<String> existingFiles = new ArrayList<String>();
550
551 if (context.getBooleanParameter(_NAMESPACE, "attachments") &&
552 message.isAttachments()) {
553
554 List<Element> attachmentEls = messageEl.elements("attachment");
555
556 for (Element attachmentEl : attachmentEls) {
557 String name = attachmentEl.attributeValue("name");
558 String binPath = attachmentEl.attributeValue("bin-path");
559
560 byte[] bytes = context.getZipEntryAsByteArray(binPath);
561
562 files.add(new ObjectValuePair<String, byte[]>(name, bytes));
563 }
564
565 if (files.size() <= 0) {
566 _log.error(
567 "Could not find attachments for message " +
568 message.getMessageId());
569 }
570 }
571
572 String[] tagsEntries = null;
573
574 if (context.getBooleanParameter(_NAMESPACE, "tags")) {
575 tagsEntries = context.getTagsEntries(
576 MBMessage.class, message.getMessageId());
577 }
578
579 PortletPreferences prefs = null;
580
581 boolean addCommunityPermissions = true;
582 boolean addGuestPermissions = true;
583
584 ThemeDisplay themeDisplay = null;
585
586 MBMessage existingMessage = null;
587
588 try {
589 MBCategoryUtil.findByPrimaryKey(categoryId);
590
591 if (parentMessageId != MBMessageImpl.DEFAULT_PARENT_MESSAGE_ID) {
592 MBMessageUtil.findByPrimaryKey(parentMessageId);
593 MBThreadUtil.findByPrimaryKey(threadId);
594 }
595
596 if (context.getDataStrategy().equals(
597 PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
598
599 try {
600 existingMessage = MBMessageFinderUtil.findByUuid_G(
601 message.getUuid(), context.getGroupId());
602
603 MBMessageLocalServiceUtil.updateMessage(
604 userId, existingMessage.getMessageId(),
605 message.getSubject(), message.getBody(), files,
606 existingFiles, message.getPriority(), tagsEntries,
607 prefs, themeDisplay);
608 }
609 catch (NoSuchMessageException nsme) {
610 existingMessage = MBMessageLocalServiceUtil.addMessage(
611 message.getUuid(), userId, userName, categoryId,
612 threadId, parentMessageId, message.getSubject(),
613 message.getBody(), files, message.getAnonymous(),
614 message.getPriority(), tagsEntries, prefs,
615 addCommunityPermissions, addGuestPermissions,
616 themeDisplay);
617 }
618 }
619 else {
620 existingMessage = MBMessageLocalServiceUtil.addMessage(
621 userId, userName, categoryId, threadId, parentMessageId,
622 message.getSubject(), message.getBody(), files,
623 message.getAnonymous(), message.getPriority(), tagsEntries,
624 prefs, addCommunityPermissions, addGuestPermissions,
625 themeDisplay);
626 }
627
628 threadPKs.put(message.getThreadId(), existingMessage.getThreadId());
629 messagePKs.put(
630 message.getMessageId(), existingMessage.getMessageId());
631
632 if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
633 context.importRatingsEntries(
634 MBMessage.class, message.getMessageId(),
635 existingMessage.getMessageId());
636 }
637 }
638 catch (NoSuchCategoryException nsce) {
639 _log.error(
640 "Could not find the parent category for message " +
641 message.getMessageId());
642 }
643 catch (NoSuchMessageException nsme) {
644 _log.error(
645 "Could not find the parent message for message " +
646 message.getMessageId());
647 }
648 catch (NoSuchThreadException nste) {
649 _log.error(
650 "Could not find the thread for message " +
651 message.getMessageId());
652 }
653 }
654
655 protected String getCategoryPath(
656 PortletDataContext context, MBCategory category) {
657
658 StringBuilder sb = new StringBuilder();
659
660 sb.append(context.getPortletPath(PortletKeys.MESSAGE_BOARDS));
661 sb.append("/categories/");
662 sb.append(category.getCategoryId());
663 sb.append(".xml");
664
665 return sb.toString();
666 }
667
668 protected String getMessageAttachementBinPath(
669 PortletDataContext context, MBMessage message, String attachment) {
670
671 StringBuilder sb = new StringBuilder();
672
673 sb.append(context.getPortletPath(PortletKeys.MESSAGE_BOARDS));
674 sb.append("/bin/");
675 sb.append(message.getMessageId());
676 sb.append(StringPool.SLASH);
677 sb.append(attachment);
678
679 return sb.toString();
680 }
681
682 protected String getMessageFlagPath(
683 PortletDataContext context, MBMessageFlag messageFlag) {
684
685 StringBuilder sb = new StringBuilder();
686
687 sb.append(context.getPortletPath(PortletKeys.MESSAGE_BOARDS));
688 sb.append("/message-flags/");
689 sb.append(messageFlag.getMessageFlagId());
690 sb.append(".xml");
691
692 return sb.toString();
693 }
694
695 protected String getMessagePath(
696 PortletDataContext context, MBMessage message) {
697
698 StringBuilder sb = new StringBuilder();
699
700 sb.append(context.getPortletPath(PortletKeys.MESSAGE_BOARDS));
701 sb.append("/messages/");
702 sb.append(message.getMessageId());
703 sb.append(".xml");
704
705 return sb.toString();
706 }
707
708 protected String getUserBanPath(PortletDataContext context, MBBan ban) {
709 StringBuilder sb = new StringBuilder();
710
711 sb.append(context.getPortletPath(PortletKeys.MESSAGE_BOARDS));
712 sb.append("/user-bans/");
713 sb.append(ban.getBanId());
714 sb.append(".xml");
715
716 return sb.toString();
717 }
718
719 private static final String _NAMESPACE = "message_board";
720
721 private static final PortletDataHandlerBoolean _categoriesAndMessages =
722 new PortletDataHandlerBoolean(
723 _NAMESPACE, "categories-and-messages", true, true);
724
725 private static final PortletDataHandlerBoolean _attachments =
726 new PortletDataHandlerBoolean(_NAMESPACE, "attachments");
727
728 private static final PortletDataHandlerBoolean _userBans =
729 new PortletDataHandlerBoolean(_NAMESPACE, "user-bans");
730
731 private static final PortletDataHandlerBoolean _flags =
732 new PortletDataHandlerBoolean(_NAMESPACE, "flags");
733
734 private static final PortletDataHandlerBoolean _ratings =
735 new PortletDataHandlerBoolean(_NAMESPACE, "ratings");
736
737 private static final PortletDataHandlerBoolean _tags =
738 new PortletDataHandlerBoolean(_NAMESPACE, "tags");
739
740 private static Log _log =
741 LogFactory.getLog(MBPortletDataHandlerImpl.class);
742
743 }