001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.messageboards.service.impl;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.increment.BufferedIncrement;
020    import com.liferay.portal.kernel.increment.NumberIncrement;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.search.Indexer;
024    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
025    import com.liferay.portal.kernel.util.CharPool;
026    import com.liferay.portal.kernel.util.StringBundler;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.StringUtil;
029    import com.liferay.portal.kernel.util.Validator;
030    import com.liferay.portal.kernel.workflow.WorkflowConstants;
031    import com.liferay.portal.model.CompanyConstants;
032    import com.liferay.portal.model.ResourceConstants;
033    import com.liferay.portal.service.ServiceContext;
034    import com.liferay.portlet.documentlibrary.DuplicateDirectoryException;
035    import com.liferay.portlet.documentlibrary.NoSuchDirectoryException;
036    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
037    import com.liferay.portlet.messageboards.SplitThreadException;
038    import com.liferay.portlet.messageboards.model.MBCategory;
039    import com.liferay.portlet.messageboards.model.MBCategoryConstants;
040    import com.liferay.portlet.messageboards.model.MBMessage;
041    import com.liferay.portlet.messageboards.model.MBMessageDisplay;
042    import com.liferay.portlet.messageboards.model.MBThread;
043    import com.liferay.portlet.messageboards.model.MBThreadConstants;
044    import com.liferay.portlet.messageboards.model.MBTreeWalker;
045    import com.liferay.portlet.messageboards.service.base.MBThreadLocalServiceBaseImpl;
046    
047    import java.io.File;
048    import java.io.IOException;
049    import java.io.InputStream;
050    
051    import java.util.ArrayList;
052    import java.util.List;
053    
054    /**
055     * @author Brian Wing Shun Chan
056     * @author Shuyang Zhou
057     */
058    public class MBThreadLocalServiceImpl extends MBThreadLocalServiceBaseImpl {
059    
060            public MBThread addThread(long categoryId, MBMessage message)
061                    throws PortalException, SystemException {
062    
063                    // Thread
064    
065                    long threadId = message.getThreadId();
066    
067                    if (!message.isRoot() || (threadId <= 0)) {
068                            threadId = counterLocalService.increment();
069                    }
070    
071                    MBThread thread = mbThreadPersistence.create(threadId);
072    
073                    thread.setGroupId(message.getGroupId());
074                    thread.setCompanyId(message.getCompanyId());
075                    thread.setCategoryId(categoryId);
076                    thread.setRootMessageId(message.getMessageId());
077                    thread.setRootMessageUserId(message.getUserId());
078    
079                    if (message.isAnonymous()) {
080                            thread.setLastPostByUserId(0);
081                    }
082                    else {
083                            thread.setLastPostByUserId(message.getUserId());
084                    }
085    
086                    thread.setLastPostDate(message.getCreateDate());
087    
088                    if (message.getPriority() != MBThreadConstants.PRIORITY_NOT_GIVEN) {
089                            thread.setPriority(message.getPriority());
090                    }
091    
092                    thread.setStatus(message.getStatus());
093                    thread.setStatusByUserId(message.getStatusByUserId());
094                    thread.setStatusByUserName(message.getStatusByUserName());
095                    thread.setStatusDate(message.getStatusDate());
096    
097                    mbThreadPersistence.update(thread, false);
098    
099                    // Asset
100    
101                    if (categoryId >= 0) {
102                            assetEntryLocalService.updateEntry(
103                                    message.getUserId(), message.getGroupId(),
104                                    MBThread.class.getName(), thread.getThreadId(), null, 0,
105                                    new long[0], new String[0], false, null, null, null, null, null,
106                                    String.valueOf(thread.getRootMessageId()), null, null, null,
107                                    null, 0, 0, null, false);
108                    }
109    
110                    return thread;
111            }
112    
113            public void deleteThread(long threadId)
114                    throws PortalException, SystemException {
115    
116                    MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
117    
118                    deleteThread(thread);
119            }
120    
121            public void deleteThread(MBThread thread)
122                    throws PortalException, SystemException {
123    
124                    MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey(
125                            thread.getRootMessageId());
126    
127                    // Indexer
128    
129                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
130                            MBMessage.class);
131    
132                    indexer.delete(thread);
133    
134                    // Attachments
135    
136                    long companyId = rootMessage.getCompanyId();
137                    long repositoryId = CompanyConstants.SYSTEM;
138                    String dirName = thread.getAttachmentsDir();
139    
140                    try {
141                            DLStoreUtil.deleteDirectory(companyId, repositoryId, dirName);
142                    }
143                    catch (NoSuchDirectoryException nsde) {
144                    }
145    
146                    // Subscriptions
147    
148                    subscriptionLocalService.deleteSubscriptions(
149                            thread.getCompanyId(), MBThread.class.getName(),
150                            thread.getThreadId());
151    
152                    // Thread flags
153    
154                    mbThreadFlagPersistence.removeByThreadId(thread.getThreadId());
155    
156                    // Messages
157    
158                    List<MBMessage> messages = mbMessagePersistence.findByThreadId(
159                            thread.getThreadId());
160    
161                    for (MBMessage message : messages) {
162    
163                            // Ratings
164    
165                            ratingsStatsLocalService.deleteStats(
166                                    message.getWorkflowClassName(), message.getMessageId());
167    
168                            // Asset
169    
170                            assetEntryLocalService.deleteEntry(
171                                    message.getWorkflowClassName(), message.getMessageId());
172    
173                            // Resources
174    
175                            if (!message.isDiscussion()) {
176                                    resourceLocalService.deleteResource(
177                                            message.getCompanyId(), message.getWorkflowClassName(),
178                                            ResourceConstants.SCOPE_INDIVIDUAL, message.getMessageId());
179                            }
180    
181                            // Message
182    
183                            mbMessagePersistence.remove(message);
184    
185                            // Statistics
186    
187                            if (!message.isDiscussion()) {
188                                    mbStatsUserLocalService.updateStatsUser(
189                                            message.getGroupId(), message.getUserId());
190                            }
191    
192                            // Workflow
193    
194                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
195                                    message.getCompanyId(), message.getGroupId(),
196                                    message.getWorkflowClassName(), message.getMessageId());
197                    }
198    
199                    // Category
200    
201                    if ((rootMessage.getCategoryId() !=
202                                    MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
203                            (rootMessage.getCategoryId() !=
204                                    MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
205    
206                            MBCategory category = mbCategoryPersistence.findByPrimaryKey(
207                                    thread.getCategoryId());
208    
209                            category.setThreadCount(category.getThreadCount() - 1);
210                            category.setMessageCount(
211                                    category.getMessageCount() - thread.getMessageCount());
212    
213                            mbCategoryPersistence.update(category, false);
214                    }
215    
216                    // Thread Asset
217    
218                    assetEntryLocalService.deleteEntry(
219                            MBThread.class.getName(), thread.getThreadId());
220    
221                    // Thread
222    
223                    mbThreadPersistence.remove(thread);
224            }
225    
226            public void deleteThreads(long groupId, long categoryId)
227                    throws PortalException, SystemException {
228    
229                    List<MBThread> threads = mbThreadPersistence.findByG_C(
230                            groupId, categoryId);
231    
232                    for (MBThread thread : threads) {
233                            deleteThread(thread);
234                    }
235            }
236    
237            public MBThread fetchThread(long threadId) throws SystemException {
238                    return mbThreadPersistence.fetchByPrimaryKey(threadId);
239            }
240    
241            public int getCategoryThreadsCount(
242                            long groupId, long categoryId, int status)
243                    throws SystemException {
244    
245                    if (status == WorkflowConstants.STATUS_ANY) {
246                            return mbThreadPersistence.countByG_C(groupId, categoryId);
247                    }
248                    else {
249                            return mbThreadPersistence.countByG_C_S(
250                                    groupId, categoryId, status);
251                    }
252            }
253    
254            public List<MBThread> getGroupThreads(
255                            long groupId, int status, int start, int end)
256                    throws SystemException {
257    
258                    if (status == WorkflowConstants.STATUS_ANY) {
259                            return mbThreadPersistence.findByG_NotC(
260                                    groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, start,
261                                    end);
262                    }
263                    else {
264                            return mbThreadPersistence.findByG_NotC_S(
265                                    groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, status,
266                                    start, end);
267                    }
268            }
269    
270            public List<MBThread> getGroupThreads(
271                            long groupId, long userId, int status, boolean subscribed,
272                            boolean includeAnonymous, int start, int end)
273                    throws PortalException, SystemException {
274    
275                    if (userId <= 0) {
276                            if (status == WorkflowConstants.STATUS_ANY) {
277                                    return mbThreadPersistence.findByG_NotC(
278                                            groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, start,
279                                            end);
280                            }
281                            else {
282                                    return mbThreadPersistence.findByG_NotC_S(
283                                            groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, status,
284                                            start, end);
285                            }
286                    }
287                    else {
288                            if (subscribed) {
289                                    return mbThreadFinder.findByS_G_U_C_S(
290                                            groupId, userId, null, status, start, end);
291                            }
292                            else {
293                                    List<Long> threadIds = null;
294    
295                                    if (includeAnonymous) {
296                                            threadIds = mbMessageFinder.findByG_U_C_S(
297                                                    groupId, userId, null, status, start, end);
298                                    }
299                                    else {
300                                            threadIds = mbMessageFinder.findByG_U_C_A_S(
301                                                    groupId, userId, null, false, status, start, end);
302                                    }
303    
304                                    List<MBThread> threads = new ArrayList<MBThread>(
305                                            threadIds.size());
306    
307                                    for (long threadId : threadIds) {
308                                            MBThread thread = mbThreadPersistence.findByPrimaryKey(
309                                                    threadId);
310    
311                                            threads.add(thread);
312                                    }
313    
314                                    return threads;
315                            }
316                    }
317            }
318    
319            public List<MBThread> getGroupThreads(
320                            long groupId, long userId, int status, boolean subscribed,
321                            int start, int end)
322                    throws PortalException, SystemException {
323    
324                    return getGroupThreads(
325                            groupId, userId, status, subscribed, true, start, end);
326            }
327    
328            public List<MBThread> getGroupThreads(
329                            long groupId, long userId, int status, int start, int end)
330                    throws PortalException, SystemException {
331    
332                    return getGroupThreads(groupId, userId, status, false, start, end);
333            }
334    
335            public int getGroupThreadsCount(long groupId, int status)
336                    throws SystemException {
337    
338                    if (status == WorkflowConstants.STATUS_ANY) {
339                            return mbThreadPersistence.countByG_NotC(
340                                    groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID);
341                    }
342                    else {
343                            return mbThreadPersistence.countByG_NotC_S(
344                                    groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, status);
345                    }
346            }
347    
348            public int getGroupThreadsCount(long groupId, long userId, int status)
349                    throws SystemException {
350    
351                    return getGroupThreadsCount(groupId, userId, status, false);
352            }
353    
354            public int getGroupThreadsCount(
355                            long groupId, long userId, int status, boolean subscribed)
356                    throws SystemException {
357    
358                    return getGroupThreadsCount(groupId, userId, status, subscribed, true);
359            }
360    
361            public int getGroupThreadsCount(
362                            long groupId, long userId, int status, boolean subscribed,
363                            boolean includeAnonymous)
364                    throws SystemException {
365    
366                    if (userId <= 0) {
367                            if (status == WorkflowConstants.STATUS_ANY) {
368                                    return mbThreadPersistence.countByG_NotC(
369                                            groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID);
370                            }
371                            else {
372                                    return mbThreadPersistence.countByG_NotC_S(
373                                            groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID,
374                                            status);
375                            }
376                    }
377                    else {
378                            if (subscribed) {
379                                    return mbThreadFinder.countByS_G_U_C_S(
380                                            groupId, userId, null, status);
381                            }
382                            else {
383                                    if (includeAnonymous) {
384                                            return mbMessageFinder.countByG_U_C_S(
385                                                    groupId, userId, null, status);
386                                    }
387                                    else {
388                                            return mbMessageFinder.countByG_U_C_A_S(
389                                                    groupId, userId, null, false, status);
390                                    }
391                            }
392                    }
393            }
394    
395            public List<MBThread> getNoAssetThreads() throws SystemException {
396                    return mbThreadFinder.findByNoAssets();
397            }
398    
399            public List<MBThread> getPriorityThreads(long categoryId, double priority)
400                    throws PortalException, SystemException {
401    
402                    return getPriorityThreads(categoryId, priority, false);
403            }
404    
405            public List<MBThread> getPriorityThreads(
406                            long categoryId, double priority, boolean inherit)
407                    throws PortalException, SystemException {
408    
409                    if (!inherit) {
410                            return mbThreadPersistence.findByC_P(categoryId, priority);
411                    }
412    
413                    List<MBThread> threads = new ArrayList<MBThread>();
414    
415                    while ((categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
416                               (categoryId != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
417    
418                            threads.addAll(
419                                    0, mbThreadPersistence.findByC_P(categoryId, priority));
420    
421                            MBCategory category = mbCategoryPersistence.findByPrimaryKey(
422                                    categoryId);
423    
424                            categoryId = category.getParentCategoryId();
425                    }
426    
427                    return threads;
428            }
429    
430            public MBThread getThread(long threadId)
431                    throws PortalException, SystemException {
432    
433                    return mbThreadPersistence.findByPrimaryKey(threadId);
434            }
435    
436            public List<MBThread> getThreads(
437                            long groupId, long categoryId, int status, int start, int end)
438                    throws SystemException {
439    
440                    if (status == WorkflowConstants.STATUS_ANY) {
441                            return mbThreadPersistence.findByG_C(
442                                    groupId, categoryId, start, end);
443                    }
444                    else {
445                            return mbThreadPersistence.findByG_C_S(
446                                    groupId, categoryId, status, start, end);
447                    }
448            }
449    
450            public int getThreadsCount(long groupId, long categoryId, int status)
451                    throws SystemException {
452    
453                    if (status == WorkflowConstants.STATUS_ANY) {
454                            return mbThreadPersistence.countByG_C(groupId, categoryId);
455                    }
456                    else {
457                            return mbThreadPersistence.countByG_C_S(
458                                    groupId, categoryId, status);
459                    }
460            }
461    
462            public boolean hasAnswerMessage(long threadId) throws SystemException {
463                    int count = mbMessagePersistence.countByT_A(threadId, true);
464    
465                    if (count > 0) {
466                            return true;
467                    }
468                    else {
469                            return false;
470                    }
471            }
472    
473            @BufferedIncrement(incrementClass = NumberIncrement.class)
474            public MBThread incrementViewCounter(long threadId, int increment)
475                    throws PortalException, SystemException {
476    
477                    MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
478    
479                    thread.setViewCount(thread.getViewCount() + increment);
480    
481                    mbThreadPersistence.update(thread, false);
482    
483                    return thread;
484            }
485    
486            public MBThread moveThread(long groupId, long categoryId, long threadId)
487                    throws PortalException, SystemException {
488    
489                    MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
490    
491                    long oldCategoryId = thread.getCategoryId();
492    
493                    MBCategory oldCategory = null;
494    
495                    if (oldCategoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
496                            oldCategory = mbCategoryPersistence.findByPrimaryKey(oldCategoryId);
497                    }
498    
499                    MBCategory category = null;
500    
501                    if (categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
502                            category = mbCategoryPersistence.findByPrimaryKey(categoryId);
503                    }
504    
505                    // Messages
506    
507                    List<MBMessage> messages = mbMessagePersistence.findByG_C_T(
508                            groupId, oldCategoryId, thread.getThreadId());
509    
510                    for (MBMessage message : messages) {
511                            message.setCategoryId(categoryId);
512    
513                            mbMessagePersistence.update(message, false);
514    
515                            // Indexer
516    
517                            if (!message.isDiscussion()) {
518                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
519                                            MBMessage.class);
520    
521                                    indexer.reindex(message);
522                            }
523                    }
524    
525                    // Thread
526    
527                    thread.setCategoryId(categoryId);
528    
529                    mbThreadPersistence.update(thread, false);
530    
531                    // Category
532    
533                    if ((oldCategory != null) && (categoryId != oldCategoryId)) {
534                            oldCategory.setThreadCount(oldCategory.getThreadCount() - 1);
535                            oldCategory.setMessageCount(
536                                    oldCategory.getMessageCount() - thread.getMessageCount());
537    
538                            mbCategoryPersistence.update(oldCategory, false);
539                    }
540    
541                    if ((category != null) && (categoryId != oldCategoryId)) {
542                            category.setThreadCount(category.getThreadCount() + 1);
543                            category.setMessageCount(
544                                    category.getMessageCount() + thread.getMessageCount());
545    
546                            mbCategoryPersistence.update(category, false);
547                    }
548    
549                    return thread;
550            }
551    
552            public MBThread splitThread(
553                            long messageId, String subject, ServiceContext serviceContext)
554                    throws PortalException, SystemException {
555    
556                    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
557    
558                    if (message.isRoot()) {
559                            throw new SplitThreadException();
560                    }
561    
562                    MBCategory category = message.getCategory();
563                    MBThread oldThread = message.getThread();
564                    MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey(
565                            oldThread.getRootMessageId());
566                    String oldAttachmentsDir = message.getAttachmentsDir();
567    
568                    // Message flags
569    
570                    mbMessageLocalService.updateAnswer(message, false, true);
571    
572                    // Create new thread
573    
574                    MBThread thread = addThread(message.getCategoryId(), message);
575    
576                    // Update messages
577    
578                    if (Validator.isNotNull(subject)) {
579                            MBMessageDisplay messageDisplay =
580                                    mbMessageService.getMessageDisplay(
581                                            messageId, WorkflowConstants.STATUS_ANY,
582                                            MBThreadConstants.THREAD_VIEW_TREE, false);
583    
584                            MBTreeWalker treeWalker = messageDisplay.getTreeWalker();
585    
586                            List<MBMessage> messages = treeWalker.getMessages();
587    
588                            int[] range = treeWalker.getChildrenRange(message);
589    
590                            for (int i = range[0]; i < range[1]; i++) {
591                                    MBMessage curMessage = messages.get(i);
592    
593                                    String oldSubject = message.getSubject();
594                                    String curSubject = curMessage.getSubject();
595    
596                                    if (oldSubject.startsWith("RE: ")) {
597                                            curSubject = StringUtil.replace(
598                                                    curSubject, rootMessage.getSubject(), subject);
599                                    }
600                                    else {
601                                            curSubject = StringUtil.replace(
602                                                    curSubject, oldSubject, subject);
603                                    }
604    
605                                    curMessage.setSubject(curSubject);
606    
607                                    mbMessagePersistence.update(curMessage, false);
608                            }
609    
610                            message.setSubject(subject);
611                    }
612    
613                    message.setThreadId(thread.getThreadId());
614                    message.setRootMessageId(thread.getRootMessageId());
615                    message.setParentMessageId(0);
616                    message.setAttachmentsDir(null);
617    
618                    mbMessagePersistence.update(message, false);
619    
620                    // Attachments
621    
622                    moveAttachmentsFromOldThread(message, oldAttachmentsDir);
623    
624                    // Indexer
625    
626                    if (!message.isDiscussion()) {
627                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
628                                    MBMessage.class);
629    
630                            indexer.reindex(message);
631                    }
632    
633                    // Update children
634    
635                    int messagesMoved = 1;
636    
637                    messagesMoved += moveChildrenMessages(
638                            message, category, oldThread.getThreadId());
639    
640                    // Update new thread
641    
642                    thread.setMessageCount(messagesMoved);
643    
644                    mbThreadPersistence.update(thread, false);
645    
646                    // Update old thread
647    
648                    oldThread.setMessageCount(oldThread.getMessageCount() - messagesMoved);
649    
650                    mbThreadPersistence.update(oldThread, false);
651    
652                    // Category
653    
654                    if ((message.getCategoryId() !=
655                                    MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
656                            (message.getCategoryId() !=
657                                    MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
658    
659                            category.setThreadCount(category.getThreadCount() + 1);
660    
661                            mbCategoryPersistence.update(category, false);
662                    }
663    
664                    return thread;
665            }
666    
667            public void updateQuestion(long threadId, boolean question)
668                    throws PortalException, SystemException {
669    
670                    MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
671    
672                    if (thread.isQuestion() == question) {
673                            return;
674                    }
675    
676                    thread.setQuestion(question);
677    
678                    mbThreadPersistence.update(thread, false);
679    
680                    if (!question) {
681                            MBMessage message = mbMessagePersistence.findByPrimaryKey(
682                                    thread.getRootMessageId());
683    
684                            mbMessageLocalService.updateAnswer(message, false, true);
685                    }
686            }
687    
688            /**
689             * @deprecated {@link #incrementViewCounter(long, int)}
690             */
691            public MBThread updateThread(long threadId, int viewCount)
692                    throws PortalException, SystemException {
693    
694                    MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
695    
696                    thread.setViewCount(viewCount);
697    
698                    mbThreadPersistence.update(thread, false);
699    
700                    return thread;
701            }
702    
703            protected void moveAttachmentFromOldThread(
704                            long companyId, String fileName, String newAttachmentsDir)
705                    throws PortalException, SystemException {
706    
707                    long repositoryId = CompanyConstants.SYSTEM;
708    
709                    StringBundler sb = new StringBundler(4);
710    
711                    sb.append(newAttachmentsDir);
712                    sb.append(StringPool.SLASH);
713                    sb.append(StringUtil.extractLast(fileName, CharPool.SLASH));
714    
715                    String newFileName = sb.toString();
716    
717                    try {
718                            File file = DLStoreUtil.getFile(companyId, repositoryId, fileName);
719    
720                            DLStoreUtil.addFile(
721                                    companyId, repositoryId, newFileName, false, file);
722                    }
723                    catch (UnsupportedOperationException uoe) {
724                            InputStream is = DLStoreUtil.getFileAsStream(
725                                    companyId, repositoryId, fileName);
726    
727                            try {
728                                    DLStoreUtil.addFile(
729                                            companyId, repositoryId, newFileName, false, is);
730                            }
731                            finally {
732                                    try {
733                                            is.close();
734                                    }
735                                    catch (IOException ioe) {
736                                            _log.error(ioe);
737                                    }
738                            }
739                    }
740    
741                    DLStoreUtil.deleteFile(companyId, repositoryId, fileName);
742            }
743    
744            protected void moveAttachmentsFromOldThread(
745                            MBMessage message, String oldAttachmentsDir)
746                    throws PortalException, SystemException {
747    
748                    if (!message.getAttachments()) {
749                            return;
750                    }
751    
752                    long companyId = message.getCompanyId();
753                    long repositoryId = CompanyConstants.SYSTEM;
754                    String newAttachmentsDir = message.getAttachmentsDir();
755    
756                    try {
757                            DLStoreUtil.addDirectory(
758                                    companyId, repositoryId, newAttachmentsDir);
759                    }
760                    catch (DuplicateDirectoryException dde) {
761                    }
762    
763                    String[] fileNames = DLStoreUtil.getFileNames(
764                            companyId, repositoryId, oldAttachmentsDir);
765    
766                    for (String fileName : fileNames) {
767                            moveAttachmentFromOldThread(companyId, fileName, newAttachmentsDir);
768                    }
769    
770                    try {
771                            DLStoreUtil.deleteDirectory(
772                                    companyId, repositoryId, oldAttachmentsDir);
773                    }
774                    catch (NoSuchDirectoryException nsde) {
775                    }
776            }
777    
778            protected int moveChildrenMessages(
779                            MBMessage parentMessage, MBCategory category, long oldThreadId)
780                    throws PortalException, SystemException {
781    
782                    int messagesMoved = 0;
783    
784                    List<MBMessage> messages = mbMessagePersistence.findByT_P(
785                            oldThreadId, parentMessage.getMessageId());
786    
787                    for (MBMessage message : messages) {
788                            String oldAttachmentsDir = message.getAttachmentsDir();
789    
790                            message.setCategoryId(parentMessage.getCategoryId());
791                            message.setThreadId(parentMessage.getThreadId());
792                            message.setRootMessageId(parentMessage.getRootMessageId());
793                            message.setAttachmentsDir(null);
794    
795                            mbMessagePersistence.update(message, false);
796    
797                            moveAttachmentsFromOldThread(message, oldAttachmentsDir);
798    
799                            if (!message.isDiscussion()) {
800                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
801                                            MBMessage.class);
802    
803                                    indexer.reindex(message);
804                            }
805    
806                            messagesMoved++;
807    
808                            messagesMoved += moveChildrenMessages(
809                                    message, category, oldThreadId);
810                    }
811    
812                    return messagesMoved;
813            }
814    
815            private static Log _log = LogFactoryUtil.getLog(
816                    MBThreadLocalServiceImpl.class);
817    
818    }