Java tutorial
/* * Copyright (c) 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.application.djigzo.ws.impl; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.mail.MessagingException; import javax.mail.internet.AddressException; import javax.mail.internet.MimeMessage; import javax.mail.util.ByteArrayDataSource; import mitm.application.djigzo.james.DjigzoMailAttributes; import mitm.application.djigzo.james.DjigzoMailAttributesImpl; import mitm.application.djigzo.james.JamesStoreManager; import mitm.application.djigzo.mail.MailSerializer; import mitm.application.djigzo.ws.BinaryDTO; import mitm.application.djigzo.ws.MailRepositoryItemDTO; import mitm.application.djigzo.ws.MailRepositoryWS; import mitm.application.djigzo.ws.PolicyViolationDTO; import mitm.application.djigzo.ws.ReleaseProcessor; import mitm.common.dlp.PolicyViolation; import mitm.common.hibernate.annotations.StartTransaction; import mitm.common.mail.EmailAddressUtils; import mitm.common.mail.MailUtils; import mitm.common.mail.MimeTypes; import mitm.common.mail.repository.MailRepository; import mitm.common.mail.repository.MailRepositoryEventListener; import mitm.common.mail.repository.MailRepositoryItem; import mitm.common.mail.repository.MailRepositorySearchField; import mitm.common.util.Check; import mitm.common.ws.WebServiceCheckedException; import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.service.ServiceManager; import org.apache.commons.lang.StringUtils; import org.apache.james.core.MailImpl; import org.apache.mailet.Mail; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Implementation of MailRepositoryWS. * * @author Martijn Brinkers * */ public class MailRepositoryWSImpl implements MailRepositoryWS { private final static Logger logger = LoggerFactory.getLogger(MailRepositoryWSImpl.class); /* * The actual MailRepository. */ private final MailRepository mailRepository; /* * The next processor for normal released message */ private final String defaultProcessor; /* * The next processor for released message that must be encrypted */ private final String forceEncryptProcessor; /* * The next processor for released message that should be send without further processing */ private final String sendAsIsProcessor; /* * ServiceManager is used for injecting the released mail into the James spool. */ private final ServiceManager serviceManager; /* * Is used to tell listeners that something has happened for on the mailRepository. */ private final MailRepositoryEventListener mailRepositoryEventListener; public MailRepositoryWSImpl(MailRepository mailRepository, String defaultProcessor, String forceEncryptProcessor, String sendAsIsProcessor, ServiceManager serviceManager, MailRepositoryEventListener mailRepositoryEventListener) { Check.notNull(mailRepository, "mailRepository"); Check.notNull(defaultProcessor, "defaultProcessor"); Check.notNull(forceEncryptProcessor, "forceEncryptProcessor"); Check.notNull(sendAsIsProcessor, "sendAsIsProcessor"); Check.notNull(serviceManager, "serviceManager"); Check.notNull(mailRepositoryEventListener, "mailRepositoryEventListener"); this.mailRepository = mailRepository; this.defaultProcessor = defaultProcessor; this.forceEncryptProcessor = forceEncryptProcessor; this.sendAsIsProcessor = sendAsIsProcessor; this.serviceManager = serviceManager; this.mailRepositoryEventListener = mailRepositoryEventListener; } private MailRepositoryItem getItemInternal(String id) throws WebServiceCheckedException { if (id == null) { throw new WebServiceCheckedException("id is missing."); } MailRepositoryItem item = mailRepository.getItem(id); if (item == null) { throw new WebServiceCheckedException("Mail Repository item with id " + id + " was not found."); } return item; } /* * We will assume that this MailRepositoryItem stores a MailContainer object in * the AdditionalData and that the mail item contains information about DLP policy * violations. If we need to make this class more general we can subclass it * and create a quarantine exension. */ private Mail getMail(MailRepositoryItem item) { Mail mail = null; byte[] additionalData = item.getAdditionalData(); if (additionalData != null) { mail = new MailSerializer().deserialize(additionalData); } return mail; } private MailRepositoryItemDTO toDTO(MailRepositoryItem item) { MailRepositoryItemDTO dto = new MailRepositoryItemDTO(); dto.setId(item.getID()); dto.setRepository(item.getRepository()); dto.setMessageID(item.getMessageID()); dto.setSubject(item.getSubject()); dto.setFromHeader(item.getFromHeader()); try { dto.setRecipients( EmailAddressUtils.addressesToStrings(item.getRecipients(), false /* do not decode */)); } catch (AddressException e) { logger.error("Exception getting recipients.", e); } try { dto.setSender(EmailAddressUtils.getEmailAddress(item.getSender())); } catch (AddressException e) { logger.error("Exception getting sender.", e); } try { dto.setOriginator(EmailAddressUtils.getEmailAddress(item.getOriginator())); } catch (AddressException e) { logger.error("Exception getting originator.", e); } dto.setRemoteAddress(item.getRemoteAddress()); dto.setCreated(item.getCreated()); /* * We will assume that this MailRepositoryItem stores a MailContainer object in * the AdditionalData and that the mail item contains information about DLP policy * violations. If we need to make this class more general we can subclass it * and create a quarantine exension. */ Mail mail = getMail(item); if (mail != null) { DjigzoMailAttributes mailAttributes = new DjigzoMailAttributesImpl(mail); dto.setInfo(mailAttributes.getPolicyViolationErrorMessage()); Collection<PolicyViolation> violations = mailAttributes.getPolicyViolations(); if (violations != null) { List<PolicyViolationDTO> violationsDTOs = new ArrayList<PolicyViolationDTO>(violations.size()); for (PolicyViolation violation : violations) { violationsDTOs.add(new PolicyViolationDTO(violation)); } dto.setPolicyViolations(violationsDTOs); } } return dto; } @Override @StartTransaction public MailRepositoryItemDTO getItem(String id) throws WebServiceCheckedException { if (id == null) { throw new WebServiceCheckedException("id is missing."); } MailRepositoryItem item = mailRepository.getItem(id); return item != null ? toDTO(item) : null; } @Override @StartTransaction public void deleteItem(String id) throws WebServiceCheckedException { if (id == null) { throw new WebServiceCheckedException("id is missing."); } MailRepositoryItem item = mailRepository.getItem(id); if (item != null) { mailRepository.deleteItem(id); mailRepositoryEventListener.onDeleted(mailRepository.getName(), item); } } @Override @StartTransaction public BinaryDTO getMimeMessage(String id) throws WebServiceCheckedException { try { MimeMessage message = getItemInternal(id).getMimeMessage(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); MailUtils.writeMessage(message, bos); DataSource source = new ByteArrayDataSource(bos.toByteArray(), MimeTypes.OCTET_STREAM); DataHandler dataHandler = new DataHandler(source); return new BinaryDTO(dataHandler); } catch (MessagingException e) { throw new WebServiceCheckedException("Error while getting MimeMessage", e); } catch (IOException e) { throw new WebServiceCheckedException("Error while getting MimeMessage", e); } } @Override @StartTransaction public List<MailRepositoryItemDTO> getItems(Integer firstResult, Integer maxResults) throws WebServiceCheckedException { List<MailRepositoryItemDTO> result = new LinkedList<MailRepositoryItemDTO>(); List<? extends MailRepositoryItem> items = mailRepository.getItems(firstResult, maxResults); for (MailRepositoryItem item : items) { result.add(toDTO(item)); } return result; } @Override @StartTransaction public List<MailRepositoryItemDTO> searchItems(MailRepositorySearchField searchField, String key, Integer firstResult, Integer maxResults) throws WebServiceCheckedException { if (searchField == null) { throw new WebServiceCheckedException("searchField is missing."); } key = StringUtils.defaultString(key); List<MailRepositoryItemDTO> result = new LinkedList<MailRepositoryItemDTO>(); List<? extends MailRepositoryItem> items = mailRepository.searchItems(searchField, key, firstResult, maxResults); for (MailRepositoryItem item : items) { result.add(toDTO(item)); } return result; } @Override @StartTransaction public int getItemCount() throws WebServiceCheckedException { return mailRepository.getItemCount(); } @Override @StartTransaction public int getSearchCount(MailRepositorySearchField searchField, String key) throws WebServiceCheckedException { if (searchField == null) { throw new WebServiceCheckedException("searchField is missing."); } key = StringUtils.defaultString(key); return mailRepository.getSearchCount(searchField, key); } @Override @StartTransaction public void releaseMessage(String id, ReleaseProcessor processor) throws WebServiceCheckedException { try { if (processor == null) { throw new WebServiceCheckedException("processor is missing."); } MailRepositoryItem item = getItemInternal(id); Mail mail = getMail(item); if (mail == null) { throw new WebServiceCheckedException("Error release message. Mail not found."); } mail.setMessage(item.getMimeMessage()); switch (processor) { case DEFAULT: mail.setState(defaultProcessor); break; case ENCRYPT: mail.setState(forceEncryptProcessor); break; case AS_IS: mail.setState(sendAsIsProcessor); break; default: throw new WebServiceCheckedException("Unknown processor: " + processor); } JamesStoreManager storemanager = new JamesStoreManager(serviceManager); try { storemanager.store(mail); } finally { if (mail instanceof MailImpl) { ((MailImpl) mail).dispose(); } } mailRepositoryEventListener.onReleased(mailRepository.getName(), item); /* * Remove the message from repository because it has just been re-spooled */ mailRepository.deleteItem(id); } catch (MessagingException e) { throw new WebServiceCheckedException("Error release message.", e); } catch (ServiceException e) { throw new WebServiceCheckedException("Error release message.", e); } } }