mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	125606 rmunteanu: Merged 5.1.1 (5.1.1) to 5.1.N (5.1.2)
      125515 slanglois: MNT-16155 Update source headers - add new Copyrights for Java and JSP source files + automatic check in the build
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@125788 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
		
	
		
			
				
	
	
		
			778 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			778 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| /*
 | ||
|  * #%L
 | ||
|  * Alfresco Repository
 | ||
|  * %%
 | ||
|  * Copyright (C) 2005 - 2016 Alfresco Software Limited
 | ||
|  * %%
 | ||
|  * This file is part of the Alfresco software. 
 | ||
|  * If the software was purchased under a paid Alfresco license, the terms of 
 | ||
|  * the paid license agreement will prevail.  Otherwise, the software is 
 | ||
|  * provided under the following open source license terms:
 | ||
|  * 
 | ||
|  * 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/>.
 | ||
|  * #L%
 | ||
|  */
 | ||
| package org.alfresco.repo.imap;
 | ||
| 
 | ||
| import java.io.BufferedInputStream;
 | ||
| import java.io.FileInputStream;
 | ||
| import java.io.IOException;
 | ||
| import java.io.InputStream;
 | ||
| import java.io.SequenceInputStream;
 | ||
| import java.io.Serializable;
 | ||
| import java.util.Arrays;
 | ||
| import java.util.LinkedList;
 | ||
| import java.util.List;
 | ||
| import java.util.Map;
 | ||
| import java.util.Properties;
 | ||
| 
 | ||
| import javax.mail.Address;
 | ||
| import javax.mail.Folder;
 | ||
| import javax.mail.Message;
 | ||
| import javax.mail.MessagingException;
 | ||
| import javax.mail.Session;
 | ||
| import javax.mail.Store;
 | ||
| import javax.mail.internet.InternetAddress;
 | ||
| import javax.mail.internet.MimeMessage;
 | ||
| import javax.mail.internet.MimeMultipart;
 | ||
| import javax.mail.internet.MimeUtility;
 | ||
| import javax.transaction.UserTransaction;
 | ||
| 
 | ||
| import junit.framework.TestCase;
 | ||
| 
 | ||
| import org.alfresco.model.ContentModel;
 | ||
| import org.alfresco.model.ImapModel;
 | ||
| import org.alfresco.repo.importer.ACPImportPackageHandler;
 | ||
| import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
 | ||
| import org.alfresco.repo.node.integrity.IntegrityChecker;
 | ||
| import org.alfresco.repo.search.QueryParameterDefImpl;
 | ||
| import org.alfresco.service.ServiceRegistry;
 | ||
| import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
 | ||
| import org.alfresco.service.cmr.model.FileFolderService;
 | ||
| import org.alfresco.service.cmr.model.FileFolderUtil;
 | ||
| import org.alfresco.service.cmr.model.FileInfo;
 | ||
| import org.alfresco.service.cmr.repository.ContentWriter;
 | ||
| import org.alfresco.service.cmr.repository.NodeRef;
 | ||
| import org.alfresco.service.cmr.repository.NodeService;
 | ||
| import org.alfresco.service.cmr.repository.StoreRef;
 | ||
| import org.alfresco.service.cmr.search.QueryParameterDefinition;
 | ||
| import org.alfresco.service.cmr.search.SearchService;
 | ||
| import org.alfresco.service.cmr.security.MutableAuthenticationService;
 | ||
| import org.alfresco.service.cmr.security.PersonService;
 | ||
| import org.alfresco.service.cmr.view.ImporterService;
 | ||
| import org.alfresco.service.cmr.view.Location;
 | ||
| import org.alfresco.service.namespace.NamespaceService;
 | ||
| import org.alfresco.service.namespace.QName;
 | ||
| import org.alfresco.service.transaction.TransactionService;
 | ||
| import org.alfresco.test_category.OwnJVMTestsCategory;
 | ||
| import org.alfresco.util.ApplicationContextHelper;
 | ||
| import org.alfresco.util.GUID;
 | ||
| import org.alfresco.util.PropertyMap;
 | ||
| import org.alfresco.util.config.RepositoryFolderConfigBean;
 | ||
| import org.apache.commons.logging.Log;
 | ||
| import org.apache.commons.logging.LogFactory;
 | ||
| import org.junit.experimental.categories.Category;
 | ||
| import org.springframework.context.ApplicationContext;
 | ||
| import org.springframework.core.io.ClassPathResource;
 | ||
| import org.springframework.mail.javamail.MimeMessageHelper;
 | ||
| 
 | ||
| import com.sun.mail.iap.ProtocolException;
 | ||
| import com.sun.mail.iap.Response;
 | ||
| import com.sun.mail.imap.IMAPFolder;
 | ||
| import com.sun.mail.imap.protocol.BODY;
 | ||
| import com.sun.mail.imap.protocol.FetchResponse;
 | ||
| import com.sun.mail.imap.protocol.IMAPProtocol;
 | ||
| import com.sun.mail.imap.protocol.IMAPResponse;
 | ||
| import com.sun.mail.imap.protocol.RFC822DATA;
 | ||
| import com.sun.mail.imap.protocol.UID;
 | ||
| import com.sun.mail.util.ASCIIUtility;
 | ||
| 
 | ||
| @Category(OwnJVMTestsCategory.class)
 | ||
| public class ImapMessageTest extends TestCase
 | ||
| {
 | ||
|     private static Log logger = LogFactory.getLog(ImapMessageTest.class);
 | ||
| 
 | ||
|     // IMAP client settings
 | ||
|     private static final String PROTOCOL = "imap";
 | ||
|     private static final String HOST = "localhost";
 | ||
|     private static final int PORT = 7143;
 | ||
| 
 | ||
|     private static final String ADMIN_USER_NAME = "admin";
 | ||
|     private static final String ADMIN_USER_PASSWORD = "admin";
 | ||
|     private static final String IMAP_FOLDER_NAME = "test";
 | ||
| 
 | ||
|     private Session session = null;
 | ||
|     private Store store = null;
 | ||
|     private IMAPFolder folder = null;
 | ||
| 
 | ||
|     private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
 | ||
|     private ServiceRegistry serviceRegistry;
 | ||
|     private TransactionService transactionService;
 | ||
|     private NodeService nodeService;
 | ||
|     private ImporterService importerService;
 | ||
|     private PersonService personService;
 | ||
|     private SearchService searchService;
 | ||
|     private NamespaceService namespaceService;
 | ||
|     private FileFolderService fileFolderService;
 | ||
|     private MutableAuthenticationService authenticationService;
 | ||
|     private AlfrescoImapServer imapServer;
 | ||
| 
 | ||
|     String anotherUserName;
 | ||
|     private NodeRef testImapFolderNodeRef;
 | ||
|     private NodeRef storeRootNodeRef;
 | ||
|     private final String storePath = "workspace://SpacesStore";
 | ||
|     private final String companyHomePathInStore = "/app:company_home";
 | ||
| 
 | ||
|     private static final String TEST_FOLDER = "Alfresco IMAP/" + IMAP_FOLDER_NAME + "/___-___folder_a/" + "___-___folder_a_a";
 | ||
|     private static final String TEST_FILE = "/" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + IMAP_FOLDER_NAME + "/" + NamespaceService.CONTENT_MODEL_PREFIX
 | ||
|             + ":___-___folder_a/" + NamespaceService.CONTENT_MODEL_PREFIX + ":___-___folder_a_a/" + NamespaceService.CONTENT_MODEL_PREFIX + ":___-___file_a_a";
 | ||
| 
 | ||
|     @Override
 | ||
|     public void setUp() throws Exception
 | ||
|     {
 | ||
|         logger.debug("In SetUp");
 | ||
|         serviceRegistry = (ServiceRegistry) ctx.getBean("ServiceRegistry");
 | ||
|         transactionService = serviceRegistry.getTransactionService();
 | ||
|         nodeService = serviceRegistry.getNodeService();
 | ||
|         importerService = serviceRegistry.getImporterService();
 | ||
|         personService = serviceRegistry.getPersonService();
 | ||
|         authenticationService = serviceRegistry.getAuthenticationService();
 | ||
|         searchService = serviceRegistry.getSearchService();
 | ||
|         namespaceService = serviceRegistry.getNamespaceService();
 | ||
|         fileFolderService = serviceRegistry.getFileFolderService();
 | ||
| 
 | ||
| 
 | ||
|         // start the transaction
 | ||
|         UserTransaction txn = transactionService.getUserTransaction();
 | ||
|         txn.begin();
 | ||
|         authenticationService.authenticate(ADMIN_USER_NAME, ADMIN_USER_PASSWORD.toCharArray());
 | ||
| 
 | ||
|         // downgrade integrity
 | ||
|         IntegrityChecker.setWarnInTransaction();
 | ||
| 
 | ||
|         anotherUserName = "user" + System.currentTimeMillis();
 | ||
| 
 | ||
|         PropertyMap testUser = new PropertyMap();
 | ||
|         testUser.put(ContentModel.PROP_USERNAME, anotherUserName);
 | ||
|         testUser.put(ContentModel.PROP_FIRSTNAME, anotherUserName);
 | ||
|         testUser.put(ContentModel.PROP_LASTNAME, anotherUserName);
 | ||
|         testUser.put(ContentModel.PROP_EMAIL, anotherUserName + "@alfresco.com");
 | ||
|         testUser.put(ContentModel.PROP_JOBTITLE, "jobTitle");
 | ||
| 
 | ||
|         personService.createPerson(testUser);
 | ||
| 
 | ||
|         // create the ACEGI Authentication instance for the new user
 | ||
|         authenticationService.createAuthentication(anotherUserName, anotherUserName.toCharArray());
 | ||
| 
 | ||
|         StoreRef storeRef = new StoreRef(storePath);
 | ||
|         storeRootNodeRef = nodeService.getRootNode(storeRef);
 | ||
| 
 | ||
|         List<NodeRef> nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false);
 | ||
|         NodeRef companyHomeNodeRef = nodeRefs.get(0);
 | ||
| 
 | ||
|         nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore + "/" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + IMAP_FOLDER_NAME, null,
 | ||
|                 namespaceService, false);
 | ||
|         if (nodeRefs != null && nodeRefs.size() > 0)
 | ||
|         {
 | ||
|             fileFolderService.delete(nodeRefs.get(0));
 | ||
|         }
 | ||
| 
 | ||
|         ChildApplicationContextFactory imap = (ChildApplicationContextFactory) ctx.getBean("imap");
 | ||
|         ApplicationContext imapCtx = imap.getApplicationContext();
 | ||
|         ImapServiceImpl imapServiceImpl = (ImapServiceImpl) imapCtx.getBean("imapService");
 | ||
|         imapServer = (AlfrescoImapServer) imapCtx.getBean("imapServer");
 | ||
|         
 | ||
|         if(!imapServer.isImapServerEnabled())
 | ||
|         {
 | ||
|             imapServer.setImapServerEnabled(true);
 | ||
|             imapServer.setHost(HOST);
 | ||
|             imapServer.setPort(PORT);
 | ||
|             imapServer.startup();
 | ||
|         }
 | ||
| 
 | ||
|         // Creating IMAP test folder for IMAP root
 | ||
|         LinkedList<String> folders = new LinkedList<String>();
 | ||
|         folders.add(IMAP_FOLDER_NAME);
 | ||
|         FileFolderUtil.makeFolders(fileFolderService, companyHomeNodeRef, folders, ContentModel.TYPE_FOLDER);
 | ||
| 
 | ||
|         // Setting IMAP root
 | ||
|         RepositoryFolderConfigBean imapHome = new RepositoryFolderConfigBean();
 | ||
|         imapHome.setStore(storePath);
 | ||
|         imapHome.setRootPath(companyHomePathInStore);
 | ||
|         imapHome.setFolderPath(NamespaceService.CONTENT_MODEL_PREFIX + ":" + IMAP_FOLDER_NAME);
 | ||
|         imapServiceImpl.setImapHome(imapHome);
 | ||
| 
 | ||
| 
 | ||
|         // Starting IMAP
 | ||
|         imapServiceImpl.startupInTxn(true);
 | ||
| 
 | ||
|         nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore + "/" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + IMAP_FOLDER_NAME, null,
 | ||
|                 namespaceService, false);
 | ||
|         testImapFolderNodeRef = nodeRefs.get(0);
 | ||
| 
 | ||
|         /*
 | ||
|          * Importing test folders: Test folder contains: "___-___folder_a" "___-___folder_a" contains: "___-___folder_a_a", "___-___file_a", "Message_485.eml" (this is IMAP
 | ||
|          * Message) "___-___folder_a_a" contains: "____-____file_a_a"
 | ||
|          */
 | ||
|         importInternal("imap/imapservice_test_folder_a.acp", testImapFolderNodeRef);
 | ||
| 
 | ||
|         txn.commit();
 | ||
| 
 | ||
|         // Init mail client session
 | ||
|         Properties props = new Properties();
 | ||
|         props.setProperty("mail.imap.partialfetch", "false");
 | ||
|         this.session = Session.getDefaultInstance(props, null);
 | ||
| 
 | ||
|         // Get the store
 | ||
|         this.store = session.getStore(PROTOCOL);
 | ||
|         //this.store.connect(HOST, PORT, anotherUserName, anotherUserName);
 | ||
|         this.store.connect(imapServer.getHost(), imapServer.getPort(), anotherUserName, anotherUserName);
 | ||
| 
 | ||
|         // Get folder
 | ||
|         folder = (IMAPFolder) store.getFolder(TEST_FOLDER);
 | ||
|         folder.open(Folder.READ_ONLY);
 | ||
|         
 | ||
|         logger.debug("End SetUp");
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|     private void importInternal(String acpName, NodeRef space) throws IOException
 | ||
|     {
 | ||
|         // Importing IMAP test acp
 | ||
|         ClassPathResource acpResource = new ClassPathResource(acpName);
 | ||
|         ACPImportPackageHandler acpHandler = new ACPImportPackageHandler(acpResource.getFile(), null);
 | ||
|         Location importLocation = new Location(space);
 | ||
|         importerService.importView(acpHandler, importLocation, null, null);
 | ||
|     }
 | ||
| 
 | ||
|     public void testMessageModifiedBetweenReads() throws Exception
 | ||
|     {
 | ||
|         // Get test message UID
 | ||
|         final Long uid = getMessageUid(folder, 1);
 | ||
| 
 | ||
|         // Get unmodified message
 | ||
|         BODY body = getMessageBody(folder, uid);
 | ||
| 
 | ||
|         // Parse the multipart MIME message
 | ||
|         MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()), new BufferedInputStream(body.getByteArrayInputStream()));
 | ||
| 
 | ||
|         // Reading first part - should be successful
 | ||
|         MimeMultipart content = (MimeMultipart) message.getContent();
 | ||
|         assertNotNull(content.getBodyPart(0).getContent());
 | ||
|         // Reading second part - should be successful
 | ||
|         assertNotNull(content.getBodyPart(1).getContent());
 | ||
| 
 | ||
|         // Modify message. The size of letter describing the node may change
 | ||
|         // These changes should be committed because it should be visible from client
 | ||
|         NodeRef contentNode = findNode(companyHomePathInStore + TEST_FILE);
 | ||
|         UserTransaction txn = transactionService.getUserTransaction();
 | ||
|         txn.begin();
 | ||
|         ContentWriter writer = fileFolderService.getWriter(contentNode);
 | ||
|         StringBuffer sb = new StringBuffer();
 | ||
|         for (int i = 0; i < 2000; i++)
 | ||
|         {
 | ||
|             sb.append("test string");
 | ||
|         }
 | ||
|         writer.putContent(sb.toString());
 | ||
|         txn.commit();
 | ||
| 
 | ||
|         // Read updated message part
 | ||
|         BODY bodyNew = getMessageBody(folder, uid);
 | ||
|         
 | ||
|         // The body should be updated
 | ||
|         assertFalse(Arrays.equals(bodyNew.getByteArray().getBytes(), body.getByteArray().getBytes()));
 | ||
| 
 | ||
|         // Parse the multipart MIME message
 | ||
|         message = new MimeMessage(Session.getDefaultInstance(new Properties()), new BufferedInputStream(bodyNew.getByteArrayInputStream()));
 | ||
| 
 | ||
|         // Reading first part - should be successful
 | ||
|         content = (MimeMultipart) message.getContent();
 | ||
|         assertNotNull(content.getBodyPart(0).getContent());
 | ||
|         // Reading second part - should be successful
 | ||
|         assertNotNull(content.getBodyPart(1).getContent());
 | ||
|     }
 | ||
| 
 | ||
|     public void testMessageRenamedBetweenReads() throws Exception
 | ||
|     {
 | ||
|         // Get test message UID
 | ||
|         final Long uid = getMessageUid(folder, 1);
 | ||
|         // Get Message size
 | ||
|         final int count = getMessageSize(folder, uid);
 | ||
| 
 | ||
|         // Get first part
 | ||
|         // Split the message into 2 part using a non multiple of 4 - 103 is a prime number
 | ||
|         // as the BASE64Decoder may not throw the IOException
 | ||
|         // see MNT-12995
 | ||
|         BODY body = getMessageBodyPart(folder, uid, 0, count - 103);
 | ||
| 
 | ||
|         // Rename message. The size of letter describing the node will change
 | ||
|         // These changes should be committed because it should be visible from client
 | ||
|         NodeRef contentNode = findNode(companyHomePathInStore + TEST_FILE);
 | ||
|         UserTransaction txn = transactionService.getUserTransaction();
 | ||
|         txn.begin();
 | ||
|         fileFolderService.rename(contentNode, "testtesttesttesttesttesttesttesttesttest");
 | ||
|         txn.commit();
 | ||
| 
 | ||
|         // Read second message part
 | ||
|         BODY bodyRest = getMessageBodyPart(folder, uid, count - 103, 103);
 | ||
| 
 | ||
|         // Creating and parsing message from 2 parts
 | ||
|         MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()), new SequenceInputStream(new BufferedInputStream(body.getByteArrayInputStream()),
 | ||
|                 new BufferedInputStream(bodyRest.getByteArrayInputStream())));
 | ||
| 
 | ||
|         // Reading first part - should be successful
 | ||
|         MimeMultipart content = (MimeMultipart) message.getContent();
 | ||
|         assertNotNull(content.getBodyPart(0).getContent());
 | ||
| 
 | ||
|         try
 | ||
|         {
 | ||
|             // Reading second part cause error
 | ||
|             content.getBodyPart(1).getContent();
 | ||
|             fail("Should raise an IOException");
 | ||
|         }
 | ||
|         catch (IOException e)
 | ||
|         {
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     public void dontTestMessageCache() throws Exception
 | ||
|     {
 | ||
| 
 | ||
|         // Create messages
 | ||
|         NodeRef contentNode = findNode(companyHomePathInStore + TEST_FILE);
 | ||
|         UserTransaction txn = transactionService.getUserTransaction();
 | ||
|         txn.begin();
 | ||
| 
 | ||
|         // Create messages more than cache capacity
 | ||
|         for (int i = 0; i < 51; i++)
 | ||
|         {
 | ||
|             FileInfo fi = fileFolderService.create(nodeService.getParentAssocs(contentNode).get(0).getParentRef(), "test" + i, ContentModel.TYPE_CONTENT);
 | ||
|             ContentWriter writer = fileFolderService.getWriter(fi.getNodeRef());
 | ||
|             writer.putContent("test");
 | ||
|         }
 | ||
| 
 | ||
|         txn.commit();
 | ||
| 
 | ||
|         // Reload folder
 | ||
|         folder.close(false);
 | ||
|         folder = (IMAPFolder) store.getFolder(TEST_FOLDER);
 | ||
|         folder.open(Folder.READ_ONLY);
 | ||
| 
 | ||
|         // Read all messages
 | ||
|         for (int i = 1; i < 51; i++)
 | ||
|         {
 | ||
|             // Get test message UID
 | ||
|             final Long uid = getMessageUid(folder, i);
 | ||
|             // Get Message size
 | ||
|             final int count = getMessageSize(folder, uid);
 | ||
| 
 | ||
|             // Get first part
 | ||
|             BODY body = getMessageBodyPart(folder, uid, 0, count - 100);
 | ||
|             // Read second message part
 | ||
|             BODY bodyRest = getMessageBodyPart(folder, uid, count - 100, 100);
 | ||
| 
 | ||
|             // Creating and parsing message from 2 parts
 | ||
|             MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()), new SequenceInputStream(new BufferedInputStream(body.getByteArrayInputStream()),
 | ||
|                     new BufferedInputStream(bodyRest.getByteArrayInputStream())));
 | ||
| 
 | ||
|             // Reading first part - should be successful
 | ||
|             MimeMultipart content = (MimeMultipart) message.getContent();
 | ||
|             assertNotNull(content.getBodyPart(0).getContent());
 | ||
|             assertNotNull(content.getBodyPart(1).getContent());
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     
 | ||
|     
 | ||
|     public void testUnmodifiedMessage() throws Exception
 | ||
|     {
 | ||
|         // Get test message UID
 | ||
|         final Long uid = getMessageUid(folder, 1);
 | ||
|         // Get Message size
 | ||
|         final int count = getMessageSize(folder, uid);
 | ||
| 
 | ||
|         // Make multiple message reading
 | ||
|         for (int i = 0; i < 100; i++)
 | ||
|         {
 | ||
|             // Get random offset
 | ||
|             int n = (int) ((int) 100 * Math.random());
 | ||
| 
 | ||
|             // Get first part
 | ||
|             BODY body = getMessageBodyPart(folder, uid, 0, count - n);
 | ||
|             // Read second message part
 | ||
|             BODY bodyRest = getMessageBodyPart(folder, uid, count - n, n);
 | ||
| 
 | ||
|             // Creating and parsing message from 2 parts
 | ||
|             MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()), new SequenceInputStream(new BufferedInputStream(body.getByteArrayInputStream()),
 | ||
|                     new BufferedInputStream(bodyRest.getByteArrayInputStream())));
 | ||
| 
 | ||
|             MimeMultipart content = (MimeMultipart) message.getContent();
 | ||
|             // Reading first part - should be successful
 | ||
|             assertNotNull(content.getBodyPart(0).getContent());
 | ||
|             // Reading second part - should be successful
 | ||
|             assertNotNull(content.getBodyPart(1).getContent());
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     public void testEncodedFromToAddresses() throws Exception
 | ||
|     {
 | ||
|         // RFC1342
 | ||
|         String addressString = "ars.kov@gmail.com";
 | ||
|         String personalString = "<EFBFBD>?р<>?ений Ковальчук";
 | ||
|         InternetAddress address = new InternetAddress(addressString, personalString, "UTF-8");
 | ||
|         
 | ||
|         // Following method returns the address with quoted personal aka <["<22>?р<>?ений Ковальчук"] <ars.kov@gmail.com>>
 | ||
|         // NOTE! This should be coincided with RFC822MetadataExtracter. Would 'addresses' be quoted or not? 
 | ||
|         // String decodedAddress = address.toUnicodeString();
 | ||
|         // So, just using decode, for now
 | ||
|         String decodedAddress = MimeUtility.decodeText(address.toString());
 | ||
|         
 | ||
|         // InternetAddress.toString(new Address[] {address}) - is used in the RFC822MetadataExtracter
 | ||
|         // So, compare with that
 | ||
|         assertFalse("Non ASCII characters in the address should be encoded", decodedAddress.equals(InternetAddress.toString(new Address[] {address})));
 | ||
|         
 | ||
|         MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
 | ||
|         
 | ||
|         MimeMessageHelper messageHelper = new MimeMessageHelper(message, false, "UTF-8");
 | ||
|         
 | ||
|         messageHelper.setText("This is a sample message for ALF-5647");
 | ||
|         messageHelper.setSubject("This is a sample message for ALF-5647");
 | ||
|         messageHelper.setFrom(address);
 | ||
|         messageHelper.addTo(address);
 | ||
|         messageHelper.addCc(address);
 | ||
|         
 | ||
|         // Creating the message node in the repository
 | ||
|         String name = AlfrescoImapConst.MESSAGE_PREFIX + GUID.generate();
 | ||
|         FileInfo messageFile = fileFolderService.create(testImapFolderNodeRef, name, ContentModel.TYPE_CONTENT);
 | ||
|         // Writing a content.
 | ||
|         new IncomingImapMessage(messageFile, serviceRegistry, message);
 | ||
|         
 | ||
|         // Getting the transformed properties from the repository
 | ||
|         // cm:originator, cm:addressee, cm:addressees, imap:messageFrom, imap:messageTo, imap:messageCc
 | ||
|         Map<QName, Serializable> properties = nodeService.getProperties(messageFile.getNodeRef());
 | ||
|         
 | ||
|         String cmOriginator = (String) properties.get(ContentModel.PROP_ORIGINATOR);
 | ||
|         String cmAddressee = (String) properties.get(ContentModel.PROP_ADDRESSEE);
 | ||
|         @SuppressWarnings("unchecked")
 | ||
|         List<String> cmAddressees = (List<String>) properties.get(ContentModel.PROP_ADDRESSEES);
 | ||
|         String imapMessageFrom = (String) properties.get(ImapModel.PROP_MESSAGE_FROM);
 | ||
|         String imapMessageTo = (String) properties.get(ImapModel.PROP_MESSAGE_TO);
 | ||
|         String imapMessageCc = (String) properties.get(ImapModel.PROP_MESSAGE_CC);
 | ||
|         
 | ||
|         assertNotNull(cmOriginator);
 | ||
|         assertEquals(decodedAddress, cmOriginator);
 | ||
|         assertNotNull(cmAddressee);
 | ||
|         assertEquals(decodedAddress, cmAddressee);
 | ||
|         assertNotNull(cmAddressees);
 | ||
|         assertEquals(1, cmAddressees.size());
 | ||
|         assertEquals(decodedAddress, cmAddressees.get(0));
 | ||
|         assertNotNull(imapMessageFrom);
 | ||
|         assertEquals(decodedAddress, imapMessageFrom);
 | ||
|         assertNotNull(imapMessageTo);
 | ||
|         assertEquals(decodedAddress, imapMessageTo);
 | ||
|         assertNotNull(imapMessageCc);
 | ||
|         assertEquals(decodedAddress, imapMessageCc);
 | ||
|     }
 | ||
|     
 | ||
|     public void testEightBitMessage() throws Exception
 | ||
|     {
 | ||
| 
 | ||
|         Store lstore = session.getStore(PROTOCOL);
 | ||
|         lstore.connect(imapServer.getHost(), imapServer.getPort(), ADMIN_USER_NAME, ADMIN_USER_PASSWORD);
 | ||
| 
 | ||
|         String folderName = "Alfresco IMAP/" + IMAP_FOLDER_NAME;
 | ||
|         
 | ||
|         IMAPFolder lfolder = (IMAPFolder) lstore.getFolder(folderName);
 | ||
|         lfolder.open(Folder.READ_WRITE);
 | ||
| 
 | ||
|         InputStream messageFileInputStream1 = null;
 | ||
|         InputStream messageFileInputStream2 = null;
 | ||
|         try
 | ||
|         {
 | ||
|             ClassPathResource fileResource = new ClassPathResource("imap/test-8bit-message.eml");
 | ||
|             messageFileInputStream1 = new FileInputStream(fileResource.getFile());
 | ||
|             Message message = new MimeMessage(Session.getDefaultInstance(new Properties()), messageFileInputStream1);
 | ||
|             String subject = message.getSubject();
 | ||
|             
 | ||
|             // get original bytes for further comparation
 | ||
|             messageFileInputStream2 = new FileInputStream(fileResource.getFile());
 | ||
|             byte[] original = ASCIIUtility.getBytes(messageFileInputStream2);
 | ||
|             
 | ||
|             Message[] messages = {message};
 | ||
|             
 | ||
|             lfolder.appendMessages(messages);
 | ||
|             
 | ||
|             
 | ||
|             
 | ||
|             // The search is not implemented. 
 | ||
|             // SearchTerm term = new HeaderTerm("X-Alfresco-Unique", "test8bit");
 | ||
|             // messages = folder.search(term);
 | ||
|             
 | ||
|             // So wee need to get our test message's UID from the repo
 | ||
|             
 | ||
|             String messageXPath = companyHomePathInStore + "/" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + IMAP_FOLDER_NAME + "/*[like(@cm:title, $cm:title, true)]";
 | ||
|             
 | ||
|             QueryParameterDefinition[] params = new QueryParameterDefinition[1];
 | ||
|             params[0] = new QueryParameterDefImpl(
 | ||
|                   ContentModel.PROP_TITLE,
 | ||
|                   serviceRegistry.getDictionaryService().getDataType(DataTypeDefinition.TEXT),
 | ||
|                   true,
 | ||
|                   subject);
 | ||
| 
 | ||
|             List<NodeRef> nodeRefs = searchService.selectNodes(storeRootNodeRef, messageXPath, params, namespaceService, true);
 | ||
|             
 | ||
|             
 | ||
|             // does the message exist
 | ||
|             assertEquals(1, nodeRefs.size());
 | ||
|             
 | ||
|             NodeRef messageNodeRef = nodeRefs.get(0);
 | ||
|             
 | ||
|             // get message UID
 | ||
|             Long dbid = (Long) nodeService.getProperty(messageNodeRef, ContentModel.PROP_NODE_DBID);
 | ||
|             
 | ||
|             // fetch the massage
 | ||
|             RFC822DATA data = getRFC822Message(lfolder, dbid);
 | ||
|             
 | ||
|             assertNotNull("Can't fetch a message from the repositiry", data);
 | ||
|             
 | ||
|             byte[] processed = ASCIIUtility.getBytes(data.getByteArrayInputStream());
 | ||
|             
 | ||
|             assertTrue("Original message doesn't coincide to the message processed by the repository", Arrays.equals(original, processed));
 | ||
|         }
 | ||
|         finally
 | ||
|         {
 | ||
|             if (messageFileInputStream1 != null) messageFileInputStream1.close();
 | ||
|             if (messageFileInputStream2 != null) messageFileInputStream2.close();
 | ||
|         }
 | ||
|             
 | ||
|         // close connection
 | ||
|         lfolder.close(true);
 | ||
|         lstore.close();
 | ||
|         
 | ||
|     }
 | ||
| 
 | ||
|     
 | ||
|     private static RFC822DATA getRFC822Message(final IMAPFolder folder, final long uid) throws MessagingException
 | ||
|     {
 | ||
|         return (RFC822DATA) folder.doCommand(new IMAPFolder.ProtocolCommand()
 | ||
|         {
 | ||
|             public Object doCommand(IMAPProtocol p) throws ProtocolException
 | ||
|             {
 | ||
|                 Response[] r = p.command("UID FETCH " + uid + " (RFC822)", null);
 | ||
|                 logResponse(r);
 | ||
|                 Response response = r[r.length - 1];
 | ||
|                 if (!response.isOK())
 | ||
|                 {
 | ||
|                     throw new ProtocolException("Unable to retrieve message in RFC822 format");
 | ||
|                 }
 | ||
| 
 | ||
|                 FetchResponse fetchResponse = (FetchResponse) r[0];
 | ||
|                 return fetchResponse.getItem(RFC822DATA.class);
 | ||
|             }
 | ||
|         });
 | ||
|        
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * Returns BODY object containing desired message fragment
 | ||
|      * 
 | ||
|      * @param folder Folder containing the message
 | ||
|      * @param uid Message UID
 | ||
|      * @param from starting byte
 | ||
|      * @param count bytes to read
 | ||
|      * @return BODY containing desired message fragment
 | ||
|      * @throws MessagingException
 | ||
|      */
 | ||
|     private static BODY getMessageBodyPart(IMAPFolder folder, final Long uid, final Integer from, final Integer count) throws MessagingException
 | ||
|     {
 | ||
|         return (BODY) folder.doCommand(new IMAPFolder.ProtocolCommand()
 | ||
|         {
 | ||
|             public Object doCommand(IMAPProtocol p) throws ProtocolException
 | ||
|             {
 | ||
|                 Response[] r = p.command("UID FETCH " + uid + " (FLAGS BODY.PEEK[]<" + from + "." + count + ">)", null);
 | ||
|                 logResponse(r);
 | ||
|                 Response response = r[r.length - 1];
 | ||
| 
 | ||
|                 // Grab response
 | ||
|                 if (!response.isOK())
 | ||
|                 {
 | ||
|                     throw new ProtocolException("Unable to retrieve message part <" + from + "." + count + ">");
 | ||
|                 }
 | ||
| 
 | ||
|                 FetchResponse fetchResponse = (FetchResponse) r[0];
 | ||
|                 BODY body = (BODY) fetchResponse.getItem(com.sun.mail.imap.protocol.BODY.class);
 | ||
|                 return body;
 | ||
|             }
 | ||
|         });
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * Finds node by its path
 | ||
|      * 
 | ||
|      * @param path String
 | ||
|      * @return NodeRef
 | ||
|      */
 | ||
|     private NodeRef findNode(String path)
 | ||
|     {
 | ||
|         List<NodeRef> nodeRefs = searchService.selectNodes(storeRootNodeRef, path, null, namespaceService, false);
 | ||
|         return nodeRefs.size() > 0 ? nodeRefs.get(0) : null;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * Returns the UID of the first message in folder
 | ||
|      * 
 | ||
|      * @param folder Folder containing the message
 | ||
|      * @param msn message sequence number
 | ||
|      * @return UID of the first message
 | ||
|      * @throws MessagingException
 | ||
|      */
 | ||
|     private static Long getMessageUid(IMAPFolder folder, final int msn) throws MessagingException
 | ||
|     {
 | ||
|         return (Long) folder.doCommand(new IMAPFolder.ProtocolCommand()
 | ||
|         {
 | ||
|             public Object doCommand(IMAPProtocol p) throws ProtocolException
 | ||
|             {
 | ||
|                 String command = "FETCH " + msn + " (UID)";
 | ||
|                 Response[] r = p.command(command, null);
 | ||
|                 logResponse(r);
 | ||
|                 Response response = r[r.length - 1];
 | ||
| 
 | ||
|                 // Grab response
 | ||
|                 if (!response.isOK())
 | ||
|                 {
 | ||
|                     throw new ProtocolException("Unable to retrieve message UID");
 | ||
|                 }
 | ||
|                 
 | ||
|                 for(int i = 0 ; i < r.length; i++)
 | ||
|                 {
 | ||
|                     if(r[i] instanceof FetchResponse)
 | ||
|                     {
 | ||
|                         FetchResponse fetchResponse = (FetchResponse) r[0];
 | ||
|                         UID uid = (UID) fetchResponse.getItem(UID.class);
 | ||
|                         logger.debug("SECNUM=" + uid.seqnum + ", UID="+uid.uid);
 | ||
|                         return uid.uid;
 | ||
|                     }
 | ||
|                 }
 | ||
|                 
 | ||
|                 /**
 | ||
|                   * Uh-oh - this is where we would intermittently fall over with a class cast exception.
 | ||
|                   * The following code probes why we don't have a FetchResponse
 | ||
|                   */
 | ||
|                 StringBuffer sb = new StringBuffer();
 | ||
|                 sb.append("command="+command);
 | ||
|                 sb.append('\n');
 | ||
|                 sb.append("resp length=" + r.length);
 | ||
|                 sb.append('\n');
 | ||
|                 for(int i = 0 ; i < r.length; i++)
 | ||
|                 {
 | ||
|                     logger.error(r[i]);
 | ||
|                     sb.append("class=" + r[i].getClass().getName());
 | ||
|                     IMAPResponse unexpected = (IMAPResponse)r[i];
 | ||
|                     sb.append("key=" + unexpected.getKey());
 | ||
|                     sb.append("number=" + unexpected.getNumber());
 | ||
|                     sb.append("rest=" + unexpected.getRest());
 | ||
|                  
 | ||
|                     sb.append("r[" + i + "]=" + r[i] + '\n');
 | ||
|                 }
 | ||
|                 throw new ProtocolException("getMessageUid: "+ sb.toString());
 | ||
|             }
 | ||
|         });
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * Returns size of the message
 | ||
|      * 
 | ||
|      * @param folder Folder containing the message
 | ||
|      * @param uid Message UID
 | ||
|      * @return Returns size of the message
 | ||
|      * @throws MessagingException
 | ||
|      */
 | ||
|     private static Integer getMessageSize(IMAPFolder folder, final Long uid) throws MessagingException
 | ||
|     {
 | ||
|         return getMessageBody(folder, uid).getByteArray().getCount();
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * Returns a full message body
 | ||
|      * 
 | ||
|      * @param folder Folder containing the message
 | ||
|      * @param uid Message UID
 | ||
|      * @return Returns size of the message
 | ||
|      * @throws MessagingException
 | ||
|      */
 | ||
|     private static BODY getMessageBody(IMAPFolder folder, final Long uid) throws MessagingException
 | ||
|     {
 | ||
|         return (BODY) folder.doCommand(new IMAPFolder.ProtocolCommand()
 | ||
|         {
 | ||
|             public Object doCommand(IMAPProtocol p) throws ProtocolException
 | ||
|             {
 | ||
|                 Response[] r = p.command("UID FETCH " + uid + " (FLAGS BODY.PEEK[])", null);
 | ||
|                 logResponse(r);
 | ||
|                 Response response = r[r.length - 1];
 | ||
| 
 | ||
|                 // Grab response
 | ||
|                 if (!response.isOK())
 | ||
|                 {
 | ||
|                     throw new ProtocolException("Unable to retrieve message size");
 | ||
|                 }
 | ||
|                 FetchResponse fetchResponse = (FetchResponse) r[0];
 | ||
|                 BODY body = (BODY) fetchResponse.getItem(BODY.class);
 | ||
|                 return body;
 | ||
|             }
 | ||
|         });
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * Simple util for logging response
 | ||
|      * 
 | ||
|      * @param r response
 | ||
|      */
 | ||
|     private static void logResponse(Response[] r)
 | ||
|     {
 | ||
|         for (int i = 0; i < r.length; i++)
 | ||
|         {
 | ||
|             logger.debug(r[i]);
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     @Override
 | ||
|     public void tearDown() throws Exception
 | ||
|     {
 | ||
|         // Deleting created test environment
 | ||
|         logger.debug("tearDown ");
 | ||
| 
 | ||
|         UserTransaction txn = transactionService.getUserTransaction();
 | ||
|         txn.begin();
 | ||
| 
 | ||
|         List<NodeRef> nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore + "/" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + IMAP_FOLDER_NAME, null,
 | ||
|                 namespaceService, false);
 | ||
|         if (nodeRefs != null && nodeRefs.size() > 0)
 | ||
|         {
 | ||
|             fileFolderService.delete(nodeRefs.get(0));
 | ||
|         }
 | ||
| 
 | ||
|         authenticationService.deleteAuthentication(anotherUserName);
 | ||
|         personService.deletePerson(anotherUserName);
 | ||
| 
 | ||
|         txn.commit();
 | ||
| 
 | ||
|         // Closing client connection
 | ||
|         folder.close(false);
 | ||
|         store.close();
 | ||
|         logger.debug("tearDown end");
 | ||
|     }
 | ||
| 
 | ||
| }
 |