mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	99981: Merged 5.0.N (5.0.2) to HEAD-BUG-FIX (5.1/Cloud) (PARTIAL MERGE)
      99482: Merged DEV to 5.0.N (5.0.1)
         99198 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc typo in project alfresco-jlan
         99413 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project alfresco-jlan
         99205 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project core
         99415 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project data-model
         99227 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project file-transfer-receiver
         99416 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project legacy-lucene
         99417 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project qa-share
         99418 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project remote-api
         99427 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc in project Repository, letters S..Z
         99433 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc in project Repository, letters A..R
         99421 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project share-po
         99247 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc typo in project slingshot
         99248 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project slingshot
         99424 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project solr
         99426 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project solr4
         99253 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project solr-client
         99259 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project web-client
         99260 : MNT-13545: JavaDoc : Inconsistencies between the Java doc and the actual code
            - Changed Javadoc parameters inconsistence in project web-framework-commons
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@100501 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
		
	
		
			
				
	
	
		
			307 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			307 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2005-2010 Alfresco Software Limited.
 | |
|  *
 | |
|  * This file is part of Alfresco
 | |
|  *
 | |
|  * Alfresco is free software: you can redistribute it and/or modify
 | |
|  * it under the terms of the GNU Lesser General Public License as published by
 | |
|  * the Free Software Foundation, either version 3 of the License, or
 | |
|  * (at your option) any later version.
 | |
|  *
 | |
|  * Alfresco is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|  * GNU Lesser General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU Lesser General Public License
 | |
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | |
|  */
 | |
| package org.alfresco.repo.imap;
 | |
|  
 | |
| import java.io.ByteArrayInputStream;
 | |
| import java.io.IOException;
 | |
| import java.io.OutputStream;
 | |
| import java.io.UnsupportedEncodingException;
 | |
| import java.util.List;
 | |
|  
 | |
| import javax.mail.MessagingException;
 | |
| import javax.mail.Multipart;
 | |
| import javax.mail.Part;
 | |
| import javax.mail.internet.ContentType;
 | |
| import javax.mail.internet.MimeMessage;
 | |
| import javax.mail.internet.MimeUtility;
 | |
|  
 | |
| import org.alfresco.model.ContentModel;
 | |
| import org.alfresco.model.ImapModel;
 | |
| import org.alfresco.repo.security.authentication.AuthenticationUtil;
 | |
| import org.alfresco.repo.transaction.RetryingTransactionHelper;
 | |
| import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
 | |
| import org.alfresco.service.ServiceRegistry;
 | |
| import org.alfresco.service.cmr.model.FileFolderService;
 | |
| import org.alfresco.service.cmr.model.FileInfo;
 | |
| import org.alfresco.service.cmr.repository.ContentWriter;
 | |
| import org.alfresco.service.cmr.repository.MimetypeService;
 | |
| import org.alfresco.service.cmr.repository.NodeRef;
 | |
| import org.alfresco.service.cmr.repository.NodeService;
 | |
| import org.alfresco.service.cmr.security.PermissionService;
 | |
| import org.alfresco.util.config.RepositoryFolderConfigBean;
 | |
| import org.apache.commons.logging.Log;
 | |
| import org.apache.commons.logging.LogFactory;
 | |
| import org.apache.poi.hmef.HMEFMessage;
 | |
| import org.springframework.util.FileCopyUtils;
 | |
|  
 | |
| /**
 | |
|  * Extract attachments according to provided AttachmentsExtractorMode
 | |
|  * 
 | |
|  * @since 3.4.7
 | |
|  */
 | |
| public class AttachmentsExtractor
 | |
| {
 | |
|    public static enum AttachmentsExtractorMode
 | |
|    {
 | |
|        /**
 | |
|          * Attachments will be extracted to the same folder where email lies.
 | |
|          */
 | |
|        SAME,
 | |
|        /**
 | |
|          * All attachments for all emails will be extracted to one folder.
 | |
|          */
 | |
|        COMMON,
 | |
|        /**
 | |
|          * All attachments for each email will be extracted to separate folder.
 | |
|          */
 | |
|        SEPARATE
 | |
|    }
 | |
|  
 | |
|    private Log logger = LogFactory.getLog(AttachmentsExtractor.class);
 | |
|  
 | |
|    private FileFolderService fileFolderService;
 | |
|    private NodeService nodeService;
 | |
|     private ImapService imapService;
 | |
|    private ServiceRegistry serviceRegistry;
 | |
|    private RepositoryFolderConfigBean attachmentsFolder;
 | |
|    private NodeRef attachmentsFolderRef;
 | |
|    private AttachmentsExtractorMode attachmentsExtractorMode;
 | |
|    private MimetypeService mimetypeService;
 | |
|  
 | |
|    public void setFileFolderService(FileFolderService fileFolderService)
 | |
|    {
 | |
|        this.fileFolderService = fileFolderService;
 | |
|    }
 | |
|  
 | |
|    public void setNodeService(NodeService nodeService)
 | |
|    {
 | |
|        this.nodeService = nodeService;
 | |
|     }
 | |
| 
 | |
|     public void setImapService(ImapService imapService)
 | |
|     {
 | |
|         this.imapService = imapService;
 | |
|    }
 | |
|  
 | |
|    public void setAttachmentsFolder(RepositoryFolderConfigBean attachmentsFolder)
 | |
|    {
 | |
|        this.attachmentsFolder = attachmentsFolder;
 | |
|    }
 | |
|  
 | |
|    public void setServiceRegistry(ServiceRegistry serviceRegistry)
 | |
|    {
 | |
|        this.serviceRegistry = serviceRegistry;
 | |
|    }
 | |
|  
 | |
|    public void setAttachmentsExtractorMode(String attachmentsExtractorMode)
 | |
|    {
 | |
|        this.attachmentsExtractorMode = AttachmentsExtractorMode.valueOf(attachmentsExtractorMode);
 | |
|    }
 | |
|  
 | |
|    public void setMimetypeService(MimetypeService mimetypeService)
 | |
|    {
 | |
|        this.mimetypeService = mimetypeService;
 | |
|    }
 | |
|  
 | |
|    public void init()
 | |
|    {
 | |
|        attachmentsFolderRef = AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<NodeRef>()
 | |
|        {
 | |
|            public NodeRef doWork() throws Exception
 | |
|            {
 | |
|                RetryingTransactionHelper helper = serviceRegistry.getTransactionService().getRetryingTransactionHelper();
 | |
|                helper.setForceWritable(true);
 | |
|                RetryingTransactionCallback<NodeRef> getDescriptorCallback = new RetryingTransactionCallback<NodeRef>()
 | |
|                {
 | |
|                    public NodeRef execute() 
 | |
|                    {
 | |
|                        NodeRef attFolderRef = attachmentsFolder.getOrCreateFolderPath(serviceRegistry.getNamespaceService(), nodeService, serviceRegistry.getSearchService(), fileFolderService);
 | |
|                        if (attachmentsExtractorMode!=null && attachmentsExtractorMode==AttachmentsExtractorMode.COMMON)
 | |
|                        {
 | |
|                           serviceRegistry.getPermissionService().setPermission(attFolderRef , PermissionService.ALL_AUTHORITIES, PermissionService.FULL_CONTROL, true);
 | |
|                        }
 | |
|                        return attFolderRef;
 | |
|                    }
 | |
|                };
 | |
|                return helper.doInTransaction(getDescriptorCallback, false, false);
 | |
|            }
 | |
|        }, AuthenticationUtil.getSystemUserName());
 | |
|    }
 | |
|  
 | |
|    public void extractAttachments(NodeRef messageRef, MimeMessage originalMessage) throws IOException, MessagingException
 | |
|    {
 | |
|        NodeRef attachmentsFolderRef = null;
 | |
|        String attachmentsFolderName = null;
 | |
|        boolean createFolder = false;
 | |
|        switch (attachmentsExtractorMode)
 | |
|        {
 | |
|        case SAME:
 | |
|            attachmentsFolderRef = nodeService.getPrimaryParent(messageRef).getParentRef();
 | |
|            break;
 | |
|        case COMMON:
 | |
|            attachmentsFolderRef = this.attachmentsFolderRef;
 | |
|            break;
 | |
|        case SEPARATE:
 | |
|        default:
 | |
|            String messageName = (String) nodeService.getProperty(messageRef, ContentModel.PROP_NAME);
 | |
|            attachmentsFolderName = messageName + "-attachments";
 | |
|            createFolder = true;
 | |
|            break;
 | |
|        }
 | |
|        if (!createFolder)
 | |
|        {
 | |
|            nodeService.createAssociation(messageRef, attachmentsFolderRef, ImapModel.ASSOC_IMAP_ATTACHMENTS_FOLDER);
 | |
|        }
 | |
|  
 | |
|        Object content = originalMessage.getContent();
 | |
|        if (content instanceof Multipart)
 | |
|        {
 | |
|            Multipart multipart = (Multipart) content;
 | |
|  
 | |
|            for (int i = 0, n = multipart.getCount(); i < n; i++)
 | |
|            {
 | |
|                Part part = multipart.getBodyPart(i);
 | |
|                if ("attachment".equalsIgnoreCase(part.getDisposition()))
 | |
|                {
 | |
|                    if (createFolder)
 | |
|                    {
 | |
|                        attachmentsFolderRef = createAttachmentFolder(messageRef, attachmentsFolderName);
 | |
|                        createFolder = false;
 | |
|                    }
 | |
|                    createAttachment(messageRef, attachmentsFolderRef, part);
 | |
|                }
 | |
|            }
 | |
|        }
 | |
|  
 | |
|    }
 | |
|  
 | |
|     private NodeRef createAttachmentFolder(NodeRef messageRef, String attachmentsFolderName)
 | |
|     {
 | |
|         NodeRef attachmentsFolderRef = null;
 | |
|         NodeRef parentFolder = nodeService.getPrimaryParent(messageRef).getParentRef();
 | |
|         attachmentsFolderRef = fileFolderService.create(parentFolder, attachmentsFolderName, ContentModel.TYPE_FOLDER).getNodeRef();
 | |
|         nodeService.createAssociation(messageRef, attachmentsFolderRef, ImapModel.ASSOC_IMAP_ATTACHMENTS_FOLDER);
 | |
|         return attachmentsFolderRef;
 | |
|     }
 | |
|    
 | |
|    /**
 | |
|     * Create an attachment given a mime part
 | |
|     * 
 | |
|     * @param messageFile the file containing the message
 | |
|     * @param attachmentsFolderRef where to put the attachment
 | |
|     * @param part the mime part
 | |
|     * @throws MessagingException
 | |
|     * @throws IOException
 | |
|     */
 | |
|    private void createAttachment(NodeRef messageFile, NodeRef attachmentsFolderRef, Part part) throws MessagingException, IOException
 | |
|    {
 | |
|        String fileName = part.getFileName();
 | |
|        if (fileName == null || fileName.isEmpty())
 | |
|        {
 | |
|     	   fileName = "unnamed";
 | |
|        }
 | |
|        try
 | |
|        {
 | |
|            fileName = MimeUtility.decodeText(fileName);
 | |
|        }
 | |
|        catch (UnsupportedEncodingException e)
 | |
|        {
 | |
|            if (logger.isWarnEnabled())
 | |
|            {
 | |
|                logger.warn("Cannot decode file name '" + fileName + "'", e);
 | |
|            }
 | |
|        }
 | |
|  
 | |
|        ContentType contentType = new ContentType(part.getContentType());
 | |
|        
 | |
|         if (contentType.getBaseType().equalsIgnoreCase("application/ms-tnef"))
 | |
|         {
 | |
|             // The content is TNEF
 | |
|             HMEFMessage hmef = new HMEFMessage(part.getInputStream());
 | |
|            
 | |
|             // hmef.getBody();
 | |
|             List<org.apache.poi.hmef.Attachment> attachments = hmef.getAttachments();
 | |
|             for (org.apache.poi.hmef.Attachment attachment : attachments)
 | |
|             {
 | |
|                 String subName = attachment.getLongFilename();
 | |
|                
 | |
|                 NodeRef attachmentNode = fileFolderService.searchSimple(attachmentsFolderRef, subName);
 | |
|                 if (attachmentNode == null)
 | |
|                 {
 | |
|                     /*
 | |
|                      * If the node with the given name does not already exist Create the content node to contain the attachment
 | |
|                      */
 | |
|                     FileInfo createdFile = fileFolderService.create(attachmentsFolderRef, subName, ContentModel.TYPE_CONTENT);
 | |
|                    
 | |
|                     attachmentNode = createdFile.getNodeRef();
 | |
|                    
 | |
|                     serviceRegistry.getNodeService().createAssociation(messageFile, attachmentNode, ImapModel.ASSOC_IMAP_ATTACHMENT);
 | |
|                
 | |
|                     byte[] bytes = attachment.getContents();
 | |
|                     ContentWriter writer = fileFolderService.getWriter(attachmentNode);
 | |
|                    
 | |
|                     // TODO ENCODING - attachment.getAttribute(TNEFProperty.);
 | |
|                     String extension = attachment.getExtension();
 | |
|                     String mimetype = mimetypeService.getMimetype(extension);
 | |
|                     if (mimetype != null)
 | |
|                     {
 | |
|                         writer.setMimetype(mimetype);
 | |
|                     }
 | |
|                    
 | |
|                     OutputStream os = writer.getContentOutputStream();
 | |
|                     ByteArrayInputStream is = new ByteArrayInputStream(bytes);
 | |
|                     FileCopyUtils.copy(is, os);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             // not TNEF
 | |
|             NodeRef attachmentFile = fileFolderService.searchSimple(attachmentsFolderRef, fileName);
 | |
|             // The one possible behaviour
 | |
|             /*
 | |
|              * if (result.size() > 0) { for (FileInfo fi : result) { fileFolderService.delete(fi.getNodeRef()); } }
 | |
|              */
 | |
|             // And another one behaviour which will overwrite the content of the existing file. It is performance preferable.
 | |
|             if (attachmentFile == null)
 | |
|             {
 | |
|                 FileInfo createdFile = fileFolderService.create(attachmentsFolderRef, fileName, ContentModel.TYPE_CONTENT);
 | |
|                 nodeService.createAssociation(messageFile, createdFile.getNodeRef(), ImapModel.ASSOC_IMAP_ATTACHMENT);
 | |
|                 attachmentFile = createdFile.getNodeRef();
 | |
|             }
 | |
|             else
 | |
|             {
 | |
| 
 | |
|                 String newFileName = imapService.generateUniqueFilename(attachmentsFolderRef, fileName);
 | |
|             
 | |
|                 FileInfo createdFile = fileFolderService.create(attachmentsFolderRef, newFileName, ContentModel.TYPE_CONTENT);
 | |
|                 nodeService.createAssociation(messageFile, createdFile.getNodeRef(), ImapModel.ASSOC_IMAP_ATTACHMENT);
 | |
|                 attachmentFile = createdFile.getNodeRef();
 | |
|  
 | |
|             }
 | |
|        
 | |
|             nodeService.setProperty(attachmentFile, ContentModel.PROP_DESCRIPTION, nodeService.getProperty(messageFile, ContentModel.PROP_NAME));
 | |
|  
 | |
|             ContentWriter writer = fileFolderService.getWriter(attachmentFile);
 | |
|             writer.setMimetype(contentType.getBaseType());
 | |
|             OutputStream os = writer.getContentOutputStream();
 | |
|             FileCopyUtils.copy(part.getInputStream(), os);
 | |
|         }
 | |
|     }
 | |
| } |