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