Java tutorial
/* * Copyright (c) 2010-2011, Martijn Brinkers, Djigzo. * * This file is part of Djigzo email encryption. * * Djigzo is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License * version 3, 19 November 2007 as published by the Free Software * Foundation. * * Djigzo 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with Djigzo. If not, see <http://www.gnu.org/licenses/> * * Additional permission under GNU AGPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or * combining it with aspectjrt.jar, aspectjweaver.jar, tyrex-1.0.3.jar, * freemarker.jar, dom4j.jar, mx4j-jmx.jar, mx4j-tools.jar, * spice-classman-1.0.jar, spice-loggerstore-0.5.jar, spice-salt-0.8.jar, * spice-xmlpolicy-1.0.jar, saaj-api-1.3.jar, saaj-impl-1.3.jar, * wsdl4j-1.6.1.jar (or modified versions of these libraries), * containing parts covered by the terms of Eclipse Public License, * tyrex license, freemarker license, dom4j license, mx4j license, * Spice Software License, Common Development and Distribution License * (CDDL), Common Public License (CPL) the licensors of this Program grant * you additional permission to convey the resulting work. */ package mitm.common.mail.repository.hibernate; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Arrays; import java.util.Date; import java.util.List; import javax.mail.MessagingException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import mitm.common.hibernate.HibernateSessionSource; import mitm.common.hibernate.HibernateUtils; import mitm.common.hibernate.SessionAdapter; import mitm.common.hibernate.SessionAdapterFactory; import mitm.common.hibernate.SessionManagedAutoCommitProxyFactory; import mitm.common.hibernate.SessionManager; import mitm.common.hibernate.SessionManagerImpl; import mitm.common.hibernate.StandardHibernateSessionSourceImpl; import mitm.common.hibernate.annotations.StartTransaction; import mitm.common.mail.EmailAddressUtils; import mitm.common.mail.MailSession; import mitm.common.mail.MailUtils; import mitm.common.mail.repository.MailRepository; import mitm.common.mail.repository.MailRepositoryItem; import mitm.common.mail.repository.MailRepositorySearchField; import mitm.common.reflection.ProxyFactoryException; import mitm.common.security.crypto.impl.RandomGeneratorImpl; import mitm.common.util.IDGenerator; import mitm.common.util.SizeUtils; import mitm.common.util.UniqueIDGenerator; import org.apache.commons.lang.time.DateUtils; import org.apache.log4j.PropertyConfigurator; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; public class MailRepositoryImplTest { private static final File hibernateConfig = new File("test/resources/hibernate.cfg.xml"); private static final File testBase = new File("test/resources/testdata/mail"); private static final String DEFAULT_REPOSITORY = "quarantine"; private static SessionManager sessionManager; private static AutoTransactDelegator proxy; private static IDGenerator idGenerator; private static MimeMessage loadMessage(String filename) throws FileNotFoundException, MessagingException { File mail = new File(testBase, filename); MimeMessage message = MailUtils.loadMessage(mail); return message; } @BeforeClass public static void setUpBeforeClass() throws Exception { PropertyConfigurator.configure("conf/log4j.properties"); HibernateSessionSource sessionSource = new StandardHibernateSessionSourceImpl(hibernateConfig); sessionManager = new SessionManagerImpl(sessionSource); HibernateUtils.recreateTables(sessionSource.getHibernateConfiguration()); proxy = AutoTransactDelegator.createProxy(); idGenerator = new UniqueIDGenerator(new RandomGeneratorImpl(), 16); } @Before public void setup() throws Exception { proxy.deleteAll(); } public static class AutoTransactDelegator { public AutoTransactDelegator() { // required by AutoCommitProxyFactory } public static AutoTransactDelegator createProxy() throws ProxyFactoryException, NoSuchMethodException { AutoTransactDelegator autoTransactDelegator = new SessionManagedAutoCommitProxyFactory<AutoTransactDelegator>( AutoTransactDelegator.class, sessionManager).createProxy(); return autoTransactDelegator; } private MailRepositoryDAO getDAO() { SessionAdapter session = SessionAdapterFactory.create(sessionManager.getSession()); return new MailRepositoryDAO(session); } private MailRepository getRepository(String repositoryName) { return new MailRepositoryImpl(idGenerator, sessionManager, repositoryName); } @StartTransaction public void deleteAll() { getDAO().deleteAll(); } @StartTransaction public MailRepositoryItem createItem(String repositoryName, MimeMessage message) throws MessagingException, IOException { return getRepository(repositoryName).createItem(message); } @StartTransaction public MailRepositoryItem addItem(String repositoryName, MimeMessage message) throws MessagingException, IOException { MailRepository repository = getRepository(repositoryName); MailRepositoryItem item = repository.createItem(message); repository.addItem(item); return item; } @StartTransaction public MailRepositoryItem addItemWithDate(String repositoryName, MimeMessage message, Date created) throws MessagingException, IOException { MailRepository repository = getRepository(repositoryName); MailRepositoryItem item = ((MailRepositoryImpl) repository).createItem(message, created); repository.addItem(item); return item; } @StartTransaction public MailRepositoryItem addItem(String repositoryName, MimeMessage message, InternetAddress[] recipients, InternetAddress sender, String remoteAddress, Date lastUpdated, byte[] additionalData) throws MessagingException, IOException { MailRepository repository = getRepository(repositoryName); MailRepositoryItem item = repository.createItem(message); item.setRecipients(Arrays.asList(recipients)); item.setSender(sender); item.setRemoteAddress(remoteAddress); item.setLastUpdated(lastUpdated); item.setAdditionalData(additionalData); repository.addItem(item); return item; } @StartTransaction public void deleteItem(String repositoryName, String id) throws MessagingException, IOException { getRepository(repositoryName).deleteItem(id); } @StartTransaction public MailRepositoryItem getItem(String repositoryName, String id) throws MessagingException, IOException { return getRepository(repositoryName).getItem(id); } @StartTransaction public int getItemCount(String repositoryName) { return getRepository(repositoryName).getItemCount(); } @StartTransaction public List<String> getRecipients(String repositoryName, String id) throws MessagingException, IOException { MailRepositoryItem item = getItem(repositoryName, id); return EmailAddressUtils.addressesToStrings(item.getRecipients(), true); } @StartTransaction public List<? extends MailRepositoryItem> getItems(String repositoryName, Integer firstResult, Integer maxResults) { return getRepository(repositoryName).getItems(firstResult, maxResults); } @StartTransaction public List<? extends MailRepositoryItem> searchItems(String repositoryName, MailRepositorySearchField searchField, String key, Integer firstResult, Integer maxResults) { return getRepository(repositoryName).searchItems(searchField, key, firstResult, maxResults); } @StartTransaction public int getSearchCount(String repositoryName, MailRepositorySearchField searchField, String key) { return getRepository(repositoryName).getSearchCount(searchField, key); } @StartTransaction public List<? extends MailRepositoryItem> getItemsBefore(String repositoryName, Date before, Integer firstResult, Integer maxResults) { return getRepository(repositoryName).getItemsBefore(before, firstResult, maxResults); } @StartTransaction public void assertMessage(String repositoryName, String id, MimeMessage expected) throws MessagingException, IOException { MailRepositoryItem item = getItem(repositoryName, id); ByteArrayOutputStream bos1 = new ByteArrayOutputStream(); MailUtils.writeMessage(item.getMimeMessage(), bos1); ByteArrayOutputStream bos2 = new ByteArrayOutputStream(); MailUtils.writeMessage(expected, bos2); assertTrue(Arrays.equals(bos2.toByteArray(), bos1.toByteArray())); } } @Test public void testCreateItem() throws Exception { MimeMessage message = loadMessage("html-alternative.eml"); assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY)); MailRepositoryItem item = proxy.createItem(DEFAULT_REPOSITORY, message); assertNotNull(item); assertNotNull(item.getID()); assertNotNull(item.getCreated()); assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY)); } @Test public void testAddItem() throws Exception { MimeMessage message = loadMessage("html-alternative.eml"); assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY)); MailRepositoryItem item = proxy.addItem(DEFAULT_REPOSITORY, message); assertNotNull(item); assertEquals(1, proxy.getItemCount(DEFAULT_REPOSITORY)); assertEquals("Open Source Group Members <group-digests@linkedin.com>", item.getFromHeader()); assertEquals("From Joshua Barger and other Open Source group members on LinkedIn", item.getSubject()); assertEquals("<1266236208.59156794.1253209950952.JavaMail.app@ech3-cdn18.prod>", item.getMessageID()); item = proxy.addItem(DEFAULT_REPOSITORY, message); assertNotNull(item); assertEquals(2, proxy.getItemCount(DEFAULT_REPOSITORY)); } @Test public void testInvalidFrom() throws Exception { MimeMessage message = loadMessage("invalid-from-to-cc-reply-to.eml"); assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY)); MailRepositoryItem item = proxy.addItem(DEFAULT_REPOSITORY, message); assertNotNull(item); assertEquals(1, proxy.getItemCount(DEFAULT_REPOSITORY)); assertEquals("\"%8787\" <&^&^&^&^&^&)\"(&@^%##()||", item.getFromHeader()); } @Test public void testDeleteItem() throws Exception { MimeMessage message = loadMessage("html-alternative.eml"); assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY)); MailRepositoryItem item = proxy.addItem(DEFAULT_REPOSITORY, message); assertNotNull(item); assertEquals(1, proxy.getItemCount(DEFAULT_REPOSITORY)); proxy.deleteItem(DEFAULT_REPOSITORY, item.getID()); assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY)); } @Test public void testGetItem() throws Exception { MimeMessage message = loadMessage("html-alternative.eml"); assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY)); MailRepositoryItem item = proxy.addItem(DEFAULT_REPOSITORY, message, InternetAddress.parse("test1@example.com, test2@example.com", false), new InternetAddress("sender@example.com"), "127.0.0.1", new Date(123456), new byte[] { 1, 2, 3 }); MailRepositoryItem item2 = proxy.getItem(DEFAULT_REPOSITORY, item.getID()); assertNotNull(item2); assertEquals("Open Source Group Members <group-digests@linkedin.com>", item2.getFromHeader()); assertEquals("From Joshua Barger and other Open Source group members on LinkedIn", item2.getSubject()); assertEquals("<1266236208.59156794.1253209950952.JavaMail.app@ech3-cdn18.prod>", item2.getMessageID()); assertEquals("sender@example.com", item2.getSender().getAddress()); assertEquals("127.0.0.1", item2.getRemoteAddress()); assertEquals(123456, item2.getLastUpdated().getTime()); assertTrue(Arrays.equals(new byte[] { 1, 2, 3 }, item2.getAdditionalData())); assertEquals("[test1@example.com, test2@example.com]", proxy.getRecipients(DEFAULT_REPOSITORY, item2.getID()).toString()); proxy.assertMessage(DEFAULT_REPOSITORY, item2.getID(), message); } @Test public void testGetItems() throws Exception { MimeMessage message = loadMessage("html-alternative.eml"); assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY)); int nrOfItems = 10; for (int i = 0; i < nrOfItems; i++) { proxy.addItem(DEFAULT_REPOSITORY, message, InternetAddress.parse("test1@example.com, test2@example.com", false), null, Integer.toString(i), null, null); } assertEquals(nrOfItems, proxy.getItemCount(DEFAULT_REPOSITORY)); List<? extends MailRepositoryItem> items = proxy.getItems(DEFAULT_REPOSITORY, 0, Integer.MAX_VALUE); assertEquals(nrOfItems, items.size()); for (int i = 0; i < nrOfItems; i++) { MailRepositoryItem item = items.get(i); assertEquals(Integer.toString(i), item.getRemoteAddress()); } items = proxy.getItems(DEFAULT_REPOSITORY, 0, 1); assertEquals(1, items.size()); items = proxy.getItems(DEFAULT_REPOSITORY, 8, 100); assertEquals(2, items.size()); assertEquals("8", items.get(0).getRemoteAddress()); assertEquals("9", items.get(1).getRemoteAddress()); } @Test public void testSearch() throws Exception { MimeMessage message = loadMessage("html-alternative.eml"); assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY)); int nrOfItems = 10; for (int i = 0; i < nrOfItems; i++) { proxy.addItem(DEFAULT_REPOSITORY, message, InternetAddress.parse("test" + i + "@example.com, other@example.com", false), new InternetAddress("sender" + i + "@example.com", false), "127.0.0." + i, null, null); } assertEquals(nrOfItems, proxy.getItemCount(DEFAULT_REPOSITORY)); // search from List<? extends MailRepositoryItem> items = proxy.searchItems(DEFAULT_REPOSITORY, MailRepositorySearchField.FROM, "%linkedin%", 0, Integer.MAX_VALUE); assertEquals(10, items.size()); // search from no hits items = proxy.searchItems(DEFAULT_REPOSITORY, MailRepositorySearchField.FROM, "linkedin", 0, Integer.MAX_VALUE); assertEquals(0, items.size()); // search message ID items = proxy.searchItems(DEFAULT_REPOSITORY, MailRepositorySearchField.MESSAGE_ID, "<1266236208.59156794.1253209950952.JavaMail.app@ech3-cdn18.prod>", 3, 2); assertEquals(2, items.size()); // search subject items = proxy.searchItems(DEFAULT_REPOSITORY, MailRepositorySearchField.SUBJECT, "%OPEN SOURCE GROUP%", 3, Integer.MAX_VALUE); assertEquals(7, items.size()); // search sender items = proxy.searchItems(DEFAULT_REPOSITORY, MailRepositorySearchField.SENDER, "sender4@example.com", 0, Integer.MAX_VALUE); assertEquals(1, items.size()); assertEquals("127.0.0.4", items.get(0).getRemoteAddress()); // search recipients items = proxy.searchItems(DEFAULT_REPOSITORY, MailRepositorySearchField.RECIPIENTS, "test5@example.com", 0, Integer.MAX_VALUE); assertEquals(1, items.size()); assertEquals("127.0.0.5", items.get(0).getRemoteAddress()); // search recipients items = proxy.searchItems(DEFAULT_REPOSITORY, MailRepositorySearchField.RECIPIENTS, "other@example.com", 5, Integer.MAX_VALUE); assertEquals(5, items.size()); } @Test public void testSearchCount() throws Exception { MimeMessage message = loadMessage("html-alternative.eml"); assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY)); int nrOfItems = 10; for (int i = 0; i < nrOfItems; i++) { proxy.addItem(DEFAULT_REPOSITORY, message, InternetAddress.parse("test" + i + "@example.com, other@example.com", false), new InternetAddress("sender" + i + "@example.com", false), "127.0.0." + i, null, null); } assertEquals(nrOfItems, proxy.getItemCount(DEFAULT_REPOSITORY)); // search from assertEquals(10, proxy.getSearchCount(DEFAULT_REPOSITORY, MailRepositorySearchField.FROM, "%linkedin%")); // search from no hits assertEquals(0, proxy.getSearchCount(DEFAULT_REPOSITORY, MailRepositorySearchField.FROM, "linkedin")); // search message ID assertEquals(10, proxy.getSearchCount(DEFAULT_REPOSITORY, MailRepositorySearchField.MESSAGE_ID, "<1266236208.59156794.1253209950952.JavaMail.app@ech3-cdn18.prod>")); // search subject assertEquals(10, proxy.getSearchCount(DEFAULT_REPOSITORY, MailRepositorySearchField.SUBJECT, "%OPEN SOURCE GROUP%")); // search sender assertEquals(1, proxy.getSearchCount(DEFAULT_REPOSITORY, MailRepositorySearchField.SENDER, "sender4@example.com")); // search recipients assertEquals(1, proxy.getSearchCount(DEFAULT_REPOSITORY, MailRepositorySearchField.RECIPIENTS, "test5@example.com")); // search recipients assertEquals(10, proxy.getSearchCount(DEFAULT_REPOSITORY, MailRepositorySearchField.RECIPIENTS, "other@example.com")); } @Test public void testSorting() throws Exception { MimeMessage message = loadMessage("html-alternative.eml"); assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY)); Date now = new Date(); MailRepositoryItem item4 = proxy.addItemWithDate(DEFAULT_REPOSITORY, message, DateUtils.addHours(now, 1)); MailRepositoryItem item3 = proxy.addItemWithDate(DEFAULT_REPOSITORY, message, now); MailRepositoryItem item2 = proxy.addItemWithDate(DEFAULT_REPOSITORY, message, DateUtils.addHours(now, -1)); MailRepositoryItem item1 = proxy.addItemWithDate(DEFAULT_REPOSITORY, message, DateUtils.addHours(now, -2)); assertEquals(4, proxy.getItemCount(DEFAULT_REPOSITORY)); List<? extends MailRepositoryItem> items = proxy.getItems(DEFAULT_REPOSITORY, 0, Integer.MAX_VALUE); assertEquals(4, items.size()); assertEquals(item1.getID(), items.get(0).getID()); assertEquals(item2.getID(), items.get(1).getID()); assertEquals(item3.getID(), items.get(2).getID()); assertEquals(item4.getID(), items.get(3).getID()); items = proxy.getItems(DEFAULT_REPOSITORY, 2, Integer.MAX_VALUE); assertEquals(2, items.size()); assertEquals(item3.getID(), items.get(0).getID()); assertEquals(item4.getID(), items.get(1).getID()); items = proxy.searchItems(DEFAULT_REPOSITORY, MailRepositorySearchField.FROM, "%linkedin%", 0, Integer.MAX_VALUE); assertEquals(4, items.size()); assertEquals(item1.getID(), items.get(0).getID()); assertEquals(item2.getID(), items.get(1).getID()); assertEquals(item3.getID(), items.get(2).getID()); assertEquals(item4.getID(), items.get(3).getID()); } @Test public void testBefore() throws Exception { MimeMessage message = loadMessage("html-alternative.eml"); assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY)); Date now = new Date(); proxy.addItemWithDate(DEFAULT_REPOSITORY, message, DateUtils.addHours(now, 1)); proxy.addItemWithDate(DEFAULT_REPOSITORY, message, now); MailRepositoryItem item2 = proxy.addItemWithDate(DEFAULT_REPOSITORY, message, DateUtils.addHours(now, -1)); MailRepositoryItem item1 = proxy.addItemWithDate(DEFAULT_REPOSITORY, message, DateUtils.addHours(now, -2)); assertEquals(4, proxy.getItemCount(DEFAULT_REPOSITORY)); List<? extends MailRepositoryItem> items = proxy.getItemsBefore(DEFAULT_REPOSITORY, now, 0, Integer.MAX_VALUE); assertEquals(2, items.size()); assertEquals(item1.getID(), items.get(0).getID()); assertEquals(item2.getID(), items.get(1).getID()); } /* * Insert very large messages and check the speed of inserting and loading and whether loading all messages * does not result in a OOM (i.e., the messages should be lazy loaded). */ @Test public void testPerformance() throws Exception { MimeMessage message = new MimeMessage(MailSession.getDefaultSession()); int messageSize = 50 * SizeUtils.MB; byte[] content = new byte[messageSize]; Arrays.fill(content, (byte) 'A'); message.setContent(content, "application/octet-stream"); message.saveChanges(); MailUtils.validateMessage(message); long start = System.currentTimeMillis(); int nrOfItems = 10; for (int i = 0; i < nrOfItems; i++) { proxy.addItem(DEFAULT_REPOSITORY, message, InternetAddress.parse("test" + i + "@example.com, other@example.com", false), new InternetAddress("sender" + i + "@example.com", false), "127.0.0." + i, null, null); } double msec = (double) (System.currentTimeMillis() - start) / nrOfItems; System.out.println("msec / add:" + msec); assertTrue("Can fail on slower systems", msec < 10000); start = System.currentTimeMillis(); List<? extends MailRepositoryItem> items = proxy.getItems(DEFAULT_REPOSITORY, 0, Integer.MAX_VALUE); for (MailRepositoryItem item : items) { System.out.println(item.getID()); } msec = (double) (System.currentTimeMillis() - start) / nrOfItems; System.out.println("msec / get:" + msec); assertTrue("Can fail on slower systems", msec < 100); } }