001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.messageboards.lar;
016    
017    import com.liferay.portal.kernel.lar.BasePortletDataHandler;
018    import com.liferay.portal.kernel.lar.PortletDataContext;
019    import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
020    import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.util.CharPool;
024    import com.liferay.portal.kernel.util.MapUtil;
025    import com.liferay.portal.kernel.util.ObjectValuePair;
026    import com.liferay.portal.kernel.util.StreamUtil;
027    import com.liferay.portal.kernel.util.StringBundler;
028    import com.liferay.portal.kernel.util.StringPool;
029    import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
030    import com.liferay.portal.kernel.workflow.WorkflowConstants;
031    import com.liferay.portal.kernel.xml.Document;
032    import com.liferay.portal.kernel.xml.Element;
033    import com.liferay.portal.kernel.xml.SAXReaderUtil;
034    import com.liferay.portal.model.CompanyConstants;
035    import com.liferay.portal.model.User;
036    import com.liferay.portal.service.ServiceContext;
037    import com.liferay.portal.service.persistence.UserUtil;
038    import com.liferay.portal.util.PortletKeys;
039    import com.liferay.portal.util.PropsValues;
040    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
041    import com.liferay.portlet.messageboards.model.MBBan;
042    import com.liferay.portlet.messageboards.model.MBCategory;
043    import com.liferay.portlet.messageboards.model.MBCategoryConstants;
044    import com.liferay.portlet.messageboards.model.MBMessage;
045    import com.liferay.portlet.messageboards.model.MBThread;
046    import com.liferay.portlet.messageboards.model.MBThreadFlag;
047    import com.liferay.portlet.messageboards.service.MBBanLocalServiceUtil;
048    import com.liferay.portlet.messageboards.service.MBCategoryLocalServiceUtil;
049    import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
050    import com.liferay.portlet.messageboards.service.MBThreadFlagLocalServiceUtil;
051    import com.liferay.portlet.messageboards.service.MBThreadLocalServiceUtil;
052    import com.liferay.portlet.messageboards.service.persistence.MBBanUtil;
053    import com.liferay.portlet.messageboards.service.persistence.MBCategoryUtil;
054    import com.liferay.portlet.messageboards.service.persistence.MBMessageUtil;
055    import com.liferay.portlet.messageboards.service.persistence.MBThreadFlagUtil;
056    import com.liferay.portlet.messageboards.service.persistence.MBThreadUtil;
057    
058    import java.io.InputStream;
059    
060    import java.util.ArrayList;
061    import java.util.Collections;
062    import java.util.Iterator;
063    import java.util.List;
064    import java.util.Map;
065    
066    import javax.portlet.PortletPreferences;
067    
068    /**
069     * @author Bruno Farache
070     * @author Raymond Augé
071     */
072    public class MBPortletDataHandlerImpl extends BasePortletDataHandler {
073    
074            @Override
075            public PortletDataHandlerControl[] getExportControls() {
076                    return new PortletDataHandlerControl[] {
077                            _categoriesAndMessages, _threadFlags, _userBans
078                    };
079            }
080    
081            @Override
082            public PortletDataHandlerControl[] getExportMetadataControls() {
083                    return new PortletDataHandlerControl[] {
084                            new PortletDataHandlerBoolean(
085                                    _NAMESPACE, "message-board-messages", true, _metadataControls)
086                    };
087            }
088    
089            @Override
090            public PortletDataHandlerControl[] getImportControls() {
091                    return new PortletDataHandlerControl[] {
092                            _categoriesAndMessages, _threadFlags, _userBans
093                    };
094            }
095    
096            @Override
097            public PortletDataHandlerControl[] getImportMetadataControls() {
098                    return new PortletDataHandlerControl[] {
099                            new PortletDataHandlerBoolean(
100                                    _NAMESPACE, "message-board-messages", true, _metadataControls)
101                    };
102            }
103    
104            @Override
105            public boolean isAlwaysExportable() {
106                    return _ALWAYS_EXPORTABLE;
107            }
108    
109            @Override
110            public boolean isPublishToLiveByDefault() {
111                    return PropsValues.MESSAGE_BOARDS_PUBLISH_TO_LIVE_BY_DEFAULT;
112            }
113    
114            @Override
115            protected PortletPreferences doDeleteData(
116                            PortletDataContext portletDataContext, String portletId,
117                            PortletPreferences portletPreferences)
118                    throws Exception {
119    
120                    if (!portletDataContext.addPrimaryKey(
121                                    MBPortletDataHandlerImpl.class, "deleteData")) {
122    
123                            MBCategoryLocalServiceUtil.deleteCategories(
124                                    portletDataContext.getScopeGroupId());
125    
126                            MBThreadLocalServiceUtil.deleteThreads(
127                                    portletDataContext.getScopeGroupId(),
128                                    MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID);
129                    }
130    
131                    return null;
132            }
133    
134            @Override
135            protected String doExportData(
136                            PortletDataContext portletDataContext, String portletId,
137                            PortletPreferences portletPreferences)
138                    throws Exception {
139    
140                    portletDataContext.addPermissions(
141                            "com.liferay.portlet.messageboards",
142                            portletDataContext.getScopeGroupId());
143    
144                    Document document = SAXReaderUtil.createDocument();
145    
146                    Element rootElement = document.addElement("message-boards-data");
147    
148                    rootElement.addAttribute(
149                            "group-id", String.valueOf(portletDataContext.getScopeGroupId()));
150    
151                    Element categoriesElement = rootElement.addElement("categories");
152                    Element messagesElement = rootElement.addElement("messages");
153                    Element threadFlagsElement = rootElement.addElement("thread-flags");
154                    Element userBansElement = rootElement.addElement("user-bans");
155    
156                    List<MBCategory> categories = MBCategoryUtil.findByGroupId(
157                            portletDataContext.getScopeGroupId());
158    
159                    for (MBCategory category : categories) {
160                            exportCategory(
161                                    portletDataContext, categoriesElement, messagesElement,
162                                    threadFlagsElement, category);
163                    }
164    
165                    List<MBMessage> messages = MBMessageUtil.findByG_C(
166                            portletDataContext.getScopeGroupId(),
167                            MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID);
168    
169                    for (MBMessage message : messages) {
170                            exportMessage(
171                                    portletDataContext, categoriesElement, messagesElement,
172                                    threadFlagsElement, message);
173                    }
174    
175                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "user-bans")) {
176                            List<MBBan> bans = MBBanUtil.findByGroupId(
177                                    portletDataContext.getScopeGroupId());
178    
179                            for (MBBan ban : bans) {
180                                    exportBan(portletDataContext, userBansElement, ban);
181                            }
182                    }
183    
184                    return document.formattedString();
185            }
186    
187            @Override
188            protected PortletPreferences doImportData(
189                            PortletDataContext portletDataContext, String portletId,
190                            PortletPreferences portletPreferences, String data)
191                    throws Exception {
192    
193                    portletDataContext.importPermissions(
194                            "com.liferay.portlet.messageboards",
195                            portletDataContext.getSourceGroupId(),
196                            portletDataContext.getScopeGroupId());
197    
198                    Document document = SAXReaderUtil.read(data);
199    
200                    Element rootElement = document.getRootElement();
201    
202                    Element categoriesElement = rootElement.element("categories");
203    
204                    for (Element categoryElement : categoriesElement.elements("category")) {
205                            String path = categoryElement.attributeValue("path");
206    
207                            if (!portletDataContext.isPathNotProcessed(path)) {
208                                    continue;
209                            }
210    
211                            MBCategory category =
212                                    (MBCategory)portletDataContext.getZipEntryAsObject(path);
213    
214                            importCategory(portletDataContext, path, category);
215                    }
216    
217                    Element messagesElement = rootElement.element("messages");
218    
219                    for (Element messageElement : messagesElement.elements("message")) {
220                            String path = messageElement.attributeValue("path");
221    
222                            if (!portletDataContext.isPathNotProcessed(path)) {
223                                    continue;
224                            }
225    
226                            MBMessage message =
227                                    (MBMessage)portletDataContext.getZipEntryAsObject(path);
228    
229                            importMessage(portletDataContext, messageElement, message);
230                    }
231    
232                    if (portletDataContext.getBooleanParameter(
233                                    _NAMESPACE, "thread-flags")) {
234    
235                            Element threadFlagsElement = rootElement.element("thread-flags");
236    
237                            for (Element threadFlagElement :
238                                            threadFlagsElement.elements("thread-flag")) {
239    
240                                    String path = threadFlagElement.attributeValue("path");
241    
242                                    if (!portletDataContext.isPathNotProcessed(path)) {
243                                            continue;
244                                    }
245    
246                                    MBThreadFlag threadFlag =
247                                            (MBThreadFlag)portletDataContext.getZipEntryAsObject(path);
248    
249                                    importThreadFlag(
250                                            portletDataContext, threadFlagElement, threadFlag);
251                            }
252                    }
253    
254                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "user-bans")) {
255                            Element userBansElement = rootElement.element("user-bans");
256    
257                            for (Element userBanElement :
258                                            userBansElement.elements("user-ban")) {
259    
260                                    String path = userBanElement.attributeValue("path");
261    
262                                    if (!portletDataContext.isPathNotProcessed(path)) {
263                                            continue;
264                                    }
265    
266                                    MBBan ban = (MBBan)portletDataContext.getZipEntryAsObject(path);
267    
268                                    importBan(portletDataContext, userBanElement, ban);
269                            }
270                    }
271    
272                    return null;
273            }
274    
275            protected void exportBan(
276                            PortletDataContext portletDataContext, Element userBansElement,
277                            MBBan ban)
278                    throws Exception {
279    
280                    if (!portletDataContext.isWithinDateRange(ban.getModifiedDate())) {
281                            return;
282                    }
283    
284                    String path = getUserBanPath(portletDataContext, ban);
285    
286                    if (!portletDataContext.isPathNotProcessed(path)) {
287                            return;
288                    }
289    
290                    Element userBanElement = userBansElement.addElement("user-ban");
291    
292                    ban.setBanUserUuid(ban.getBanUserUuid());
293    
294                    portletDataContext.addClassedModel(
295                            userBanElement, path, ban, _NAMESPACE);
296            }
297    
298            protected void exportCategory(
299                            PortletDataContext portletDataContext, Element categoriesElement,
300                            Element messagesElement, Element threadFlagsElement,
301                            MBCategory category)
302                    throws Exception {
303    
304                    if (portletDataContext.isWithinDateRange(category.getModifiedDate())) {
305                            exportParentCategory(
306                                    portletDataContext, categoriesElement,
307                                    category.getParentCategoryId());
308    
309                            String path = getCategoryPath(portletDataContext, category);
310    
311                            if (portletDataContext.isPathNotProcessed(path)) {
312                                    Element categoryElement = categoriesElement.addElement(
313                                            "category");
314    
315                                    portletDataContext.addClassedModel(
316                                            categoryElement, path, category, _NAMESPACE);
317                            }
318                    }
319    
320                    List<MBMessage> messages = MBMessageUtil.findByG_C(
321                            category.getGroupId(), category.getCategoryId());
322    
323                    for (MBMessage message : messages) {
324                            exportMessage(
325                                    portletDataContext, categoriesElement, messagesElement,
326                                    threadFlagsElement, message);
327                    }
328            }
329    
330            protected void exportMessage(
331                            PortletDataContext portletDataContext, Element categoriesElement,
332                            Element messagesElement, Element threadFlagsElement,
333                            MBMessage message)
334                    throws Exception {
335    
336                    if (!portletDataContext.isWithinDateRange(message.getModifiedDate())) {
337                            return;
338                    }
339    
340                    if (message.getStatus() != WorkflowConstants.STATUS_APPROVED) {
341                            return;
342                    }
343    
344                    exportParentCategory(
345                            portletDataContext, categoriesElement, message.getCategoryId());
346    
347                    String path = getMessagePath(portletDataContext, message);
348    
349                    if (!portletDataContext.isPathNotProcessed(path)) {
350                            return;
351                    }
352    
353                    Element messageElement = messagesElement.addElement("message");
354    
355                    message.setPriority(message.getPriority());
356    
357                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "attachments") &&
358                            message.isAttachments()) {
359    
360                            for (String attachment : message.getAttachmentsFiles()) {
361                                    int pos = attachment.lastIndexOf(CharPool.FORWARD_SLASH);
362    
363                                    String name = attachment.substring(pos + 1);
364                                    String binPath = getMessageAttachementBinPath(
365                                            portletDataContext, message, name);
366    
367                                    Element attachmentElement = messageElement.addElement(
368                                            "attachment");
369    
370                                    attachmentElement.addAttribute("name", name);
371                                    attachmentElement.addAttribute("bin-path", binPath);
372    
373                                    byte[] bytes = DLStoreUtil.getFileAsBytes(
374                                            portletDataContext.getCompanyId(), CompanyConstants.SYSTEM,
375                                            attachment);
376    
377                                    portletDataContext.addZipEntry(binPath, bytes);
378                            }
379    
380                            message.setAttachmentsDir(message.getAttachmentsDir());
381                    }
382    
383                    if (portletDataContext.getBooleanParameter(
384                                    _NAMESPACE, "thread-flags")) {
385    
386                            List<MBThreadFlag> threadFlags = MBThreadFlagUtil.findByThreadId(
387                                    message.getThreadId());
388    
389                            for (MBThreadFlag threadFlag : threadFlags) {
390                                    exportThreadFlag(
391                                            portletDataContext, threadFlagsElement, threadFlag);
392                            }
393                    }
394    
395                    portletDataContext.addClassedModel(
396                            messageElement, path, message, _NAMESPACE);
397            }
398    
399            protected void exportParentCategory(
400                            PortletDataContext portletDataContext, Element categoriesElement,
401                            long categoryId)
402                    throws Exception {
403    
404                    if ((!portletDataContext.hasDateRange()) ||
405                            (categoryId == MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) ||
406                            (categoryId == MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
407    
408                            return;
409                    }
410    
411                    MBCategory category = MBCategoryUtil.findByPrimaryKey(categoryId);
412    
413                    exportParentCategory(
414                            portletDataContext, categoriesElement,
415                            category.getParentCategoryId());
416    
417                    String path = getCategoryPath(portletDataContext, category);
418    
419                    if (portletDataContext.isPathNotProcessed(path)) {
420                            Element categoryElement = categoriesElement.addElement("category");
421    
422                            portletDataContext.addClassedModel(
423                                    categoryElement, path, category, _NAMESPACE);
424                    }
425            }
426    
427            protected void exportThreadFlag(
428                            PortletDataContext portletDataContext, Element threadFlagsElement,
429                            MBThreadFlag threadFlag)
430                    throws Exception {
431    
432                    String path = getThreadFlagPath(portletDataContext, threadFlag);
433    
434                    if (!portletDataContext.isPathNotProcessed(path)) {
435                            return;
436                    }
437    
438                    Element threadFlagElement = threadFlagsElement.addElement(
439                            "thread-flag");
440    
441                    MBThread thread = MBThreadLocalServiceUtil.getThread(
442                            threadFlag.getThreadId());
443    
444                    MBMessage rootMessage = MBMessageLocalServiceUtil.getMessage(
445                            thread.getRootMessageId());
446    
447                    threadFlagElement.addAttribute(
448                            "root-message-uuid", rootMessage.getUuid());
449    
450                    portletDataContext.addClassedModel(
451                            threadFlagElement, path, threadFlag, _NAMESPACE);
452            }
453    
454            protected List<ObjectValuePair<String, InputStream>> getAttachments(
455                    PortletDataContext portletDataContext, Element messageElement,
456                    MBMessage message) {
457    
458                    if (!message.isAttachments() &&
459                            portletDataContext.getBooleanParameter(_NAMESPACE, "attachments")) {
460    
461                            return Collections.emptyList();
462                    }
463    
464                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
465                            new ArrayList<ObjectValuePair<String, InputStream>>();
466    
467                    List<Element> attachmentElements = messageElement.elements(
468                            "attachment");
469    
470                    for (Element attachmentElement : attachmentElements) {
471                            String name = attachmentElement.attributeValue("name");
472                            String binPath = attachmentElement.attributeValue("bin-path");
473    
474                            InputStream inputStream =
475                                    portletDataContext.getZipEntryAsInputStream(binPath);
476    
477                            ObjectValuePair<String, InputStream> inputStreamOVP =
478                                    new ObjectValuePair<String, InputStream>(name, inputStream);
479    
480                            inputStreamOVPs.add(inputStreamOVP);
481                    }
482    
483                    if (inputStreamOVPs.isEmpty()) {
484                            _log.error(
485                                    "Could not find attachments for message " +
486                                            message.getMessageId());
487                    }
488    
489                    return inputStreamOVPs;
490            }
491    
492            protected long getCategoryId(
493                            PortletDataContext portletDataContext, MBMessage message,
494                            Map<Long, Long> categoryPKs, long categoryId)
495                    throws Exception {
496    
497                    if ((categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
498                            (categoryId != MBCategoryConstants.DISCUSSION_CATEGORY_ID) &&
499                            (categoryId == message.getCategoryId())) {
500    
501                            String path = getImportCategoryPath(portletDataContext, categoryId);
502    
503                            MBCategory category =
504                                    (MBCategory)portletDataContext.getZipEntryAsObject(path);
505    
506                            importCategory(portletDataContext, path, category);
507    
508                            categoryId = MapUtil.getLong(
509                                    categoryPKs, message.getCategoryId(), message.getCategoryId());
510                    }
511    
512                    return categoryId;
513            }
514    
515            protected String getCategoryPath(
516                    PortletDataContext portletDataContext, MBCategory category) {
517    
518                    StringBundler sb = new StringBundler(4);
519    
520                    sb.append(
521                            portletDataContext.getPortletPath(PortletKeys.MESSAGE_BOARDS));
522                    sb.append("/categories/");
523                    sb.append(category.getCategoryId());
524                    sb.append(".xml");
525    
526                    return sb.toString();
527            }
528    
529            protected String getImportCategoryPath(
530                    PortletDataContext portletDataContext, long categoryId) {
531    
532                    StringBundler sb = new StringBundler(4);
533    
534                    sb.append(
535                            portletDataContext.getSourcePortletPath(
536                                    PortletKeys.MESSAGE_BOARDS));
537                    sb.append("/categories/");
538                    sb.append(categoryId);
539                    sb.append(".xml");
540    
541                    return sb.toString();
542            }
543    
544            protected String getMessageAttachementBinPath(
545                    PortletDataContext portletDataContext, MBMessage message,
546                    String attachment) {
547    
548                    StringBundler sb = new StringBundler(5);
549    
550                    sb.append(
551                            portletDataContext.getPortletPath(PortletKeys.MESSAGE_BOARDS));
552                    sb.append("/bin/");
553                    sb.append(message.getMessageId());
554                    sb.append(StringPool.SLASH);
555                    sb.append(PortalUUIDUtil.generate());
556    
557                    return sb.toString();
558            }
559    
560            protected String getMessagePath(
561                    PortletDataContext portletDataContext, MBMessage message) {
562    
563                    StringBundler sb = new StringBundler(4);
564    
565                    sb.append(
566                            portletDataContext.getPortletPath(PortletKeys.MESSAGE_BOARDS));
567                    sb.append("/messages/");
568                    sb.append(message.getMessageId());
569                    sb.append(".xml");
570    
571                    return sb.toString();
572            }
573    
574            protected String getThreadFlagPath(
575                    PortletDataContext portletDataContext, MBThreadFlag threadFlag) {
576    
577                    StringBundler sb = new StringBundler(4);
578    
579                    sb.append(
580                            portletDataContext.getPortletPath(PortletKeys.MESSAGE_BOARDS));
581                    sb.append("/thread-flags/");
582                    sb.append(threadFlag.getThreadFlagId());
583                    sb.append(".xml");
584    
585                    return sb.toString();
586            }
587    
588            protected String getUserBanPath(
589                    PortletDataContext portletDataContext, MBBan ban) {
590    
591                    StringBundler sb = new StringBundler(4);
592    
593                    sb.append(
594                            portletDataContext.getPortletPath(PortletKeys.MESSAGE_BOARDS));
595                    sb.append("/user-bans/");
596                    sb.append(ban.getBanId());
597                    sb.append(".xml");
598    
599                    return sb.toString();
600            }
601    
602            protected void importBan(
603                            PortletDataContext portletDataContext, Element userBanElement,
604                            MBBan ban)
605                    throws Exception {
606    
607                    long userId = portletDataContext.getUserId(ban.getUserUuid());
608    
609                    ServiceContext serviceContext = portletDataContext.createServiceContext(
610                            userBanElement, ban, _NAMESPACE);
611    
612                    List<User> users = UserUtil.findByUuid(ban.getBanUserUuid());
613    
614                    Iterator<User> itr = users.iterator();
615    
616                    if (itr.hasNext()) {
617                            User user = itr.next();
618    
619                            MBBanLocalServiceUtil.addBan(
620                                    userId, user.getUserId(), serviceContext);
621                    }
622                    else {
623                            _log.error(
624                                    "Could not find banned user with uuid " + ban.getBanUserUuid());
625                    }
626            }
627    
628            protected void importCategory(
629                            PortletDataContext portletDataContext, String categoryPath,
630                            MBCategory category)
631                    throws Exception {
632    
633                    long userId = portletDataContext.getUserId(category.getUserUuid());
634    
635                    Map<Long, Long> categoryPKs =
636                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
637                                    MBCategory.class);
638    
639                    long parentCategoryId = MapUtil.getLong(
640                            categoryPKs, category.getParentCategoryId(),
641                            category.getParentCategoryId());
642    
643                    String emailAddress = null;
644                    String inProtocol = null;
645                    String inServerName = null;
646                    int inServerPort = 0;
647                    boolean inUseSSL = false;
648                    String inUserName = null;
649                    String inPassword = null;
650                    int inReadInterval = 0;
651                    String outEmailAddress = null;
652                    boolean outCustom = false;
653                    String outServerName = null;
654                    int outServerPort = 0;
655                    boolean outUseSSL = false;
656                    String outUserName = null;
657                    String outPassword = null;
658                    boolean allowAnonymous = false;
659                    boolean mailingListActive = false;
660    
661                    ServiceContext serviceContext = portletDataContext.createServiceContext(
662                            categoryPath, category, _NAMESPACE);
663    
664                    if ((parentCategoryId !=
665                                    MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
666                            (parentCategoryId != MBCategoryConstants.DISCUSSION_CATEGORY_ID) &&
667                            (parentCategoryId == category.getParentCategoryId())) {
668    
669                            String path = getImportCategoryPath(
670                                    portletDataContext, parentCategoryId);
671    
672                            MBCategory parentCategory =
673                                    (MBCategory)portletDataContext.getZipEntryAsObject(path);
674    
675                            importCategory(portletDataContext, path, parentCategory);
676    
677                            parentCategoryId = MapUtil.getLong(
678                                    categoryPKs, category.getParentCategoryId(),
679                                    category.getParentCategoryId());
680                    }
681    
682                    MBCategory importedCategory = null;
683    
684                    if (portletDataContext.isDataStrategyMirror()) {
685                            MBCategory existingCategory = MBCategoryUtil.fetchByUUID_G(
686                                    category.getUuid(), portletDataContext.getScopeGroupId());
687    
688                            if (existingCategory == null) {
689                                    serviceContext.setUuid(category.getUuid());
690    
691                                    importedCategory = MBCategoryLocalServiceUtil.addCategory(
692                                            userId, parentCategoryId, category.getName(),
693                                            category.getDescription(), category.getDisplayStyle(),
694                                            emailAddress, inProtocol, inServerName, inServerPort,
695                                            inUseSSL, inUserName, inPassword, inReadInterval,
696                                            outEmailAddress, outCustom, outServerName, outServerPort,
697                                            outUseSSL, outUserName, outPassword, allowAnonymous,
698                                            mailingListActive, serviceContext);
699                            }
700                            else {
701                                    importedCategory = MBCategoryLocalServiceUtil.updateCategory(
702                                            existingCategory.getCategoryId(), parentCategoryId,
703                                            category.getName(), category.getDescription(),
704                                            category.getDisplayStyle(), emailAddress, inProtocol,
705                                            inServerName, inServerPort, inUseSSL, inUserName,
706                                            inPassword, inReadInterval, outEmailAddress, outCustom,
707                                            outServerName, outServerPort, outUseSSL, outUserName,
708                                            outPassword, allowAnonymous, mailingListActive, false,
709                                            serviceContext);
710                            }
711                    }
712                    else {
713                            importedCategory = MBCategoryLocalServiceUtil.addCategory(
714                                    userId, parentCategoryId, category.getName(),
715                                    category.getDescription(), category.getDisplayStyle(),
716                                    emailAddress, inProtocol, inServerName, inServerPort, inUseSSL,
717                                    inUserName, inPassword, inReadInterval, outEmailAddress,
718                                    outCustom, outServerName, outServerPort, outUseSSL, outUserName,
719                                    outPassword, allowAnonymous, mailingListActive, serviceContext);
720                    }
721    
722                    portletDataContext.importClassedModel(
723                            category, importedCategory, _NAMESPACE);
724            }
725    
726            protected void importMessage(
727                            PortletDataContext portletDataContext, Element messageElement,
728                            MBMessage message)
729                    throws Exception {
730    
731                    long userId = portletDataContext.getUserId(message.getUserUuid());
732                    String userName = message.getUserName();
733    
734                    Map<Long, Long> categoryPKs =
735                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
736                                    MBCategory.class);
737    
738                    long categoryId = MapUtil.getLong(
739                            categoryPKs, message.getCategoryId(), message.getCategoryId());
740    
741                    Map<Long, Long> threadPKs =
742                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
743                                    MBThread.class);
744    
745                    long threadId = MapUtil.getLong(threadPKs, message.getThreadId(), 0);
746    
747                    Map<Long, Long> messagePKs =
748                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
749                                    MBMessage.class);
750    
751                    long parentMessageId = MapUtil.getLong(
752                            messagePKs, message.getParentMessageId(),
753                            message.getParentMessageId());
754    
755                    List<String> existingFiles = new ArrayList<String>();
756    
757                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
758                            getAttachments(portletDataContext, messageElement, message);
759    
760                    try {
761                            ServiceContext serviceContext =
762                                    portletDataContext.createServiceContext(
763                                            messageElement, message, _NAMESPACE);
764    
765                            if (message.getStatus() != WorkflowConstants.STATUS_APPROVED) {
766                                    serviceContext.setWorkflowAction(
767                                            WorkflowConstants.ACTION_SAVE_DRAFT);
768                            }
769    
770                            categoryId = getCategoryId(
771                                    portletDataContext, message, categoryPKs, categoryId);
772    
773                            MBMessage importedMessage = null;
774    
775                            if (portletDataContext.isDataStrategyMirror()) {
776                                    MBMessage existingMessage = MBMessageUtil.fetchByUUID_G(
777                                            message.getUuid(), portletDataContext.getScopeGroupId());
778    
779                                    if (existingMessage == null) {
780                                            serviceContext.setUuid(message.getUuid());
781    
782                                            importedMessage = MBMessageLocalServiceUtil.addMessage(
783                                                    userId, userName, portletDataContext.getScopeGroupId(),
784                                                    categoryId, threadId, parentMessageId,
785                                                    message.getSubject(), message.getBody(),
786                                                    message.getFormat(), inputStreamOVPs,
787                                                    message.getAnonymous(), message.getPriority(),
788                                                    message.getAllowPingbacks(), serviceContext);
789                                    }
790                                    else {
791                                            importedMessage = MBMessageLocalServiceUtil.updateMessage(
792                                                    userId, existingMessage.getMessageId(),
793                                                    message.getSubject(), message.getBody(),
794                                                    inputStreamOVPs, existingFiles, message.getPriority(),
795                                                    message.getAllowPingbacks(), serviceContext);
796                                    }
797                            }
798                            else {
799                                    importedMessage = MBMessageLocalServiceUtil.addMessage(
800                                            userId, userName, portletDataContext.getScopeGroupId(),
801                                            categoryId, threadId, parentMessageId, message.getSubject(),
802                                            message.getBody(), message.getFormat(), inputStreamOVPs,
803                                            message.getAnonymous(), message.getPriority(),
804                                            message.getAllowPingbacks(), serviceContext);
805                            }
806    
807                            threadPKs.put(message.getThreadId(), importedMessage.getThreadId());
808    
809                            portletDataContext.importClassedModel(
810                                    message, importedMessage, _NAMESPACE);
811                    }
812                    finally {
813                            for (ObjectValuePair<String, InputStream> inputStreamOVP :
814                                            inputStreamOVPs) {
815    
816                                    InputStream inputStream = inputStreamOVP.getValue();
817    
818                                    StreamUtil.cleanUp(inputStream);
819                            }
820                    }
821            }
822    
823            protected void importThreadFlag(
824                            PortletDataContext portletDataContext, Element threadFlagElement,
825                            MBThreadFlag threadFlag)
826                    throws Exception {
827    
828                    long userId = portletDataContext.getUserId(threadFlag.getUserUuid());
829    
830                    Map<Long, Long> messagePKs =
831                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
832                                    MBMessage.class);
833    
834                    long threadId = MapUtil.getLong(
835                            messagePKs, threadFlag.getThreadId(), threadFlag.getThreadId());
836    
837                    MBThread thread = MBThreadUtil.fetchByPrimaryKey(threadId);
838    
839                    if (thread == null) {
840                            String rootMessageUuid = threadFlagElement.attributeValue(
841                                    "root-message-uuid");
842    
843                            MBMessage rootMessage = MBMessageUtil.fetchByUUID_G(
844                                    rootMessageUuid, portletDataContext.getScopeGroupId());
845    
846                            if (rootMessage != null) {
847                                    thread = rootMessage.getThread();
848                            }
849                    }
850    
851                    if (thread == null) {
852                            return;
853                    }
854    
855                    MBThreadFlagLocalServiceUtil.addThreadFlag(userId, thread);
856            }
857    
858            private static final boolean _ALWAYS_EXPORTABLE = true;
859    
860            private static final String _NAMESPACE = "message_board";
861    
862            private static Log _log = LogFactoryUtil.getLog(
863                    MBPortletDataHandlerImpl.class);
864    
865            private static PortletDataHandlerBoolean _categoriesAndMessages =
866                    new PortletDataHandlerBoolean(
867                            _NAMESPACE, "categories-and-messages", true, true);
868    
869            private static PortletDataHandlerControl[] _metadataControls =
870                    new PortletDataHandlerControl[] {
871                            new PortletDataHandlerBoolean(_NAMESPACE, "attachments"),
872                            new PortletDataHandlerBoolean(_NAMESPACE, "ratings"),
873                            new PortletDataHandlerBoolean(_NAMESPACE, "tags")
874                    };
875    
876            private static PortletDataHandlerBoolean _threadFlags =
877                    new PortletDataHandlerBoolean(_NAMESPACE, "thread-flags");
878    
879            private static PortletDataHandlerBoolean _userBans =
880                    new PortletDataHandlerBoolean(_NAMESPACE, "user-bans");
881    
882    }