mitm.application.djigzo.ws.impl.MailRepositoryWSImpl.java Source code

Java tutorial

Introduction

Here is the source code for mitm.application.djigzo.ws.impl.MailRepositoryWSImpl.java

Source

/*
 * 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);
        }
    }
}