Package com.ripariandata.timberwolf.mail.exchange

Source Code of com.ripariandata.timberwolf.mail.exchange.ExchangePump$MessageId

/**
* Copyright 2012 Riparian Data
* http://www.ripariandata.com
* contact@ripariandata.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ripariandata.timberwolf.mail.exchange;

import com.microsoft.schemas.exchange.services.x2006.messages.CreateFolderResponseType;
import com.microsoft.schemas.exchange.services.x2006.messages.CreateFolderType;
import com.microsoft.schemas.exchange.services.x2006.messages.CreateItemType;
import com.microsoft.schemas.exchange.services.x2006.messages.DeleteFolderType;
import com.microsoft.schemas.exchange.services.x2006.messages.DeleteItemType;
import com.microsoft.schemas.exchange.services.x2006.messages.FindItemResponseMessageType;
import com.microsoft.schemas.exchange.services.x2006.messages.FindItemType;
import com.microsoft.schemas.exchange.services.x2006.messages.FolderInfoResponseMessageType;
import com.microsoft.schemas.exchange.services.x2006.messages.ItemInfoResponseMessageType;
import com.microsoft.schemas.exchange.services.x2006.messages.MoveItemType;
import com.microsoft.schemas.exchange.services.x2006.messages.ResponseCodeType;
import com.microsoft.schemas.exchange.services.x2006.messages.ResponseMessageType;
import com.microsoft.schemas.exchange.services.x2006.types.BodyTypeType;
import com.microsoft.schemas.exchange.services.x2006.types.DefaultShapeNamesType;
import com.microsoft.schemas.exchange.services.x2006.types.DisposalType;
import com.microsoft.schemas.exchange.services.x2006.types.DistinguishedFolderIdNameType;
import com.microsoft.schemas.exchange.services.x2006.types.FolderType;
import com.microsoft.schemas.exchange.services.x2006.types.ItemIdType;
import com.microsoft.schemas.exchange.services.x2006.types.ItemQueryTraversalType;
import com.microsoft.schemas.exchange.services.x2006.types.ItemResponseShapeType;
import com.microsoft.schemas.exchange.services.x2006.types.MessageDispositionType;
import com.microsoft.schemas.exchange.services.x2006.types.MessageType;
import com.microsoft.schemas.exchange.services.x2006.types.NonEmptyArrayOfAllItemsType;
import com.microsoft.schemas.exchange.services.x2006.types.NonEmptyArrayOfBaseFolderIdsType;
import com.microsoft.schemas.exchange.services.x2006.types.NonEmptyArrayOfBaseItemIdsType;
import com.microsoft.schemas.exchange.services.x2006.types.NonEmptyArrayOfFoldersType;
import com.microsoft.schemas.exchange.services.x2006.types.TargetFolderIdType;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmlsoap.schemas.soap.envelope.BodyType;
import org.xmlsoap.schemas.soap.envelope.EnvelopeDocument;
import org.xmlsoap.schemas.soap.envelope.EnvelopeType;

/**
* This class puts a bunch of folders or emails into an account in exchange.
* This should only be used by integration tests.
*/
public class ExchangePump
{

    private static final Logger LOG = LoggerFactory.getLogger(ExchangePump.class);
    private static final String DECLARATION = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
    private static final String SOAP_ENCODING = "UTF-8";

    private String endpoint;
    private HttpUrlConnectionFactory connectionFactory = new SaslHttpUrlConnectionFactory();
    private String sender;

    public ExchangePump(final String exchangeUrl, final String senderEmail)
    {
        endpoint = exchangeUrl;
        sender = senderEmail;
    }

    private EnvelopeDocument createEmptyRequest(final String user)
    {
        EnvelopeDocument request = EnvelopeDocument.Factory.newInstance();
        EnvelopeType envelope = request.addNewEnvelope();
        envelope.addNewHeader().addNewExchangeImpersonation().addNewConnectingSID().setPrincipalName(user);
        return request;
    }

    /**
     * Tells Exchange to create all given 'folders' inside parentFolderId.
     * The request is performed as 'user'.
     * Will not create folders that already have ids.
     */
    private void createFolders(final String user, final TargetFolderIdType parentFolderId,
                               final String parentFolderName, final List<RequiredFolder> folders)
            throws FailedToCreateFolders
    {
        EnvelopeDocument request = createEmptyRequest(user);
        CreateFolderType createFolder = request.getEnvelope().addNewBody().addNewCreateFolder();
        createFolder.setParentFolderId(parentFolderId);
        NonEmptyArrayOfFoldersType requestedFolders = createFolder.addNewFolders();
        for (RequiredFolder folder : folders)
        {
            // Don't recreate folders that already exist
            if (folder.getId() == null)
            {
                LOG.debug("Creating folder: {}", folder.getName());
                requestedFolders.addNewFolder().setDisplayName(folder.getName());
            }
        }
        if (requestedFolders.sizeOfFolderArray() == 0)
        {
            LOG.debug("All requested folders were already created.");
            return;
        }
        CreateFolderResponseType response = sendRequest(request).getCreateFolderResponse();
        FolderInfoResponseMessageType[] array = response.getResponseMessages().getCreateFolderResponseMessageArray();
        int i = 0;
        for (FolderInfoResponseMessageType folderResponse : array)
        {
            for (FolderType folder : folderResponse.getFolders().getFolderArray())
            {
                while (folders.get(i).getId() != null)
                {
                    i++;
                }
                folders.get(i).setId(folder.getFolderId().getId());
                i++;
            }
        }
        if (i < folders.size())
        {
            LOG.error("Failed to create all folders for user: {}", user);
            LOG.error("Requested Folders in {}:", parentFolderName);
            for (RequiredFolder folder : folders)
            {
                LOG.error("  {}", folder.getName());
            }
            throw new FailedToCreateFolders(
                    "Failed to create all folders, perhaps some existed before running the test");
        }
    }

    public void createFolders(final String user, final String parent, final List<RequiredFolder> folders)
            throws FailedToCreateFolders
    {
        TargetFolderIdType parentFolder = TargetFolderIdType.Factory.newInstance();
        parentFolder.addNewFolderId().setId(parent);
        createFolders(user, parentFolder, parent, folders);
    }

    public void createFolders(final String user, final DistinguishedFolderIdNameType.Enum parent,
                              final List<RequiredFolder> folders) throws FailedToCreateFolders
    {
        TargetFolderIdType parentFolder = TargetFolderIdType.Factory.newInstance();
        parentFolder.addNewDistinguishedFolderId().setId(parent);
        createFolders(user, parentFolder, parent.toString(), folders);
    }

    public void deleteFolders(final String user, final List<RequiredFolder> folders) throws FailedToDeleteMessage
    {
        EnvelopeDocument request = createEmptyRequest(user);
        DeleteFolderType deleteFolder = request.getEnvelope().addNewBody().addNewDeleteFolder();
        deleteFolder.setDeleteType(DisposalType.HARD_DELETE);
        NonEmptyArrayOfBaseFolderIdsType doomedFolders = deleteFolder.addNewFolderIds();

        for (RequiredFolder folder : folders)
        {
            final String folderId = folder.getId();
            if (folderId != null && folderId.length() > 0)
            {
                doomedFolders.addNewFolderId().setId(folderId);
                LOG.debug("Preparing to delete folder: {}", folderId);
            }
        }
        BodyType response = sendRequest(request);
        ResponseMessageType[] responses =
                response.getDeleteFolderResponse().getResponseMessages().getDeleteFolderResponseMessageArray();
        for (ResponseMessageType resp : responses)
        {
            if (resp.getResponseCode() != ResponseCodeType.NO_ERROR)
            {
                LOG.debug(response.toString());
                throw new FailedToDeleteMessage(
                        "ResponseCode some sort of error: " + resp.getResponseCode());
            }
        }
    }

    public void deleteEmails(final String user, final List<MessageId> emails) throws FailedToDeleteMessage
    {
        EnvelopeDocument request = createEmptyRequest(user);
        DeleteItemType deleteItem = request.getEnvelope().addNewBody().addNewDeleteItem();
        deleteItem.setDeleteType(DisposalType.HARD_DELETE);
        NonEmptyArrayOfBaseItemIdsType doomedItems = deleteItem.addNewItemIds();
        for (MessageId email : emails)
        {
            String emailId = email.getId();
            doomedItems.addNewItemId().setId(emailId);
            LOG.debug("Preparing to delete email item: {}", emailId);
        }
        BodyType response = sendRequest(request);
        ResponseMessageType[] responses =
                response.getDeleteItemResponse().getResponseMessages().getDeleteItemResponseMessageArray();
        for (ResponseMessageType resp : responses)
        {
            if (resp.getResponseCode() != ResponseCodeType.NO_ERROR)
            {
                LOG.debug(response.toString());
                throw new FailedToDeleteMessage(
                        "ResponseCode some sort of error: " + resp.getResponseCode());
            }
        }
    }

    private void createEmails(final List<RequiredEmail> emails, final EnvelopeDocument request,
                              final NonEmptyArrayOfAllItemsType emptyItemsType)
            throws FailedToCreateMessage
    {
        for (RequiredEmail email : emails)
        {
            MessageType exchangeMessage = emptyItemsType.addNewMessage();
            exchangeMessage.addNewFrom().addNewMailbox().setEmailAddress(sender);
            com.microsoft.schemas.exchange.services.x2006.types.BodyType body = exchangeMessage.addNewBody();
            body.setBodyType(BodyTypeType.TEXT);
            body.setStringValue(email.getBody());
            exchangeMessage.setSubject(email.getSubject());
            exchangeMessage.addNewToRecipients().addNewMailbox().setEmailAddress(email.getTo());
            if (email.getCc() != null)
            {
                exchangeMessage.addNewCcRecipients().addNewMailbox().setEmailAddress(email.getCc());
            }
            if (email.getBcc() != null)
            {
                exchangeMessage.addNewBccRecipients().addNewMailbox().setEmailAddress(email.getBcc());
            }
        }
        BodyType response = sendRequest(request);
        ItemInfoResponseMessageType[] responses =
                response.getCreateItemResponse().getResponseMessages().getCreateItemResponseMessageArray();
        if (responses.length != emails.size())
        {
            LOG.debug(response.toString());
            throw new FailedToCreateMessage(
                    "There should have been " + emails.size() + " response message to createItem");
        }
        for (ItemInfoResponseMessageType resp : responses)
        {
            if (resp.getResponseCode() != ResponseCodeType.NO_ERROR)
            {
                LOG.debug(response.toString());
                throw new FailedToCreateMessage(
                        "ResponseCode some sort of error: " + resp.getResponseCode());
            }
        }
    }

    public void sendMessages(final List<RequiredEmail> emails) throws FailedToCreateMessage
    {
        EnvelopeDocument request = createEmptyRequest(sender);
        CreateItemType createItem = request.getEnvelope().addNewBody().addNewCreateItem();
        createItem.setMessageDisposition(MessageDispositionType.SEND_ONLY);
        NonEmptyArrayOfAllItemsType items = createItem.addNewItems();

        createEmails(emails, request, items);
    }


    public void saveDrafts(final String user, final List<RequiredEmail> drafts) throws FailedToCreateMessage
    {
        EnvelopeDocument request = createEmptyRequest(user);
        CreateItemType createItem = request.getEnvelope().addNewBody().addNewCreateItem();
        createItem.addNewSavedItemFolderId().addNewDistinguishedFolderId().setId(DistinguishedFolderIdNameType.DRAFTS);
        createItem.setMessageDisposition(MessageDispositionType.SAVE_ONLY);
        NonEmptyArrayOfAllItemsType items = createItem.addNewItems();

        createEmails(drafts, request, items);
    }

    public void sendAndSave(final String user, final List<RequiredEmail> drafts) throws FailedToCreateMessage
    {
        EnvelopeDocument request = createEmptyRequest(user);
        CreateItemType createItem = request.getEnvelope().addNewBody().addNewCreateItem();
        createItem.addNewSavedItemFolderId().addNewDistinguishedFolderId()
                  .setId(DistinguishedFolderIdNameType.SENTITEMS);
        createItem.setMessageDisposition(MessageDispositionType.SEND_AND_SAVE_COPY);
        NonEmptyArrayOfAllItemsType items = createItem.addNewItems();

        createEmails(drafts, request, items);
    }


    public HashMap<String, List<MessageId>> findItems(final String user,
                                                      final DistinguishedFolderIdNameType.Enum parent)
            throws FailedToFindMessage
    {
        HashMap<String, List<MessageId>> emailResults = new HashMap<String, List<MessageId>>();
        EnvelopeDocument request = createEmptyRequest(user);
        FindItemType findItem = request.getEnvelope().addNewBody().addNewFindItem();
        findItem.setTraversal(ItemQueryTraversalType.SHALLOW);
        ItemResponseShapeType itemShape = findItem.addNewItemShape();
        itemShape.setBaseShape(DefaultShapeNamesType.DEFAULT);
        // I tried to use ID_ONLY and add some AdditionalProperties, but the
        // schema appears to be screwy and not have FieldURI in there correctly
        findItem.addNewParentFolderIds().addNewDistinguishedFolderId().setId(parent);
        BodyType response = sendRequest(request);
        FindItemResponseMessageType responseMessage =
                response.getFindItemResponse().getResponseMessages().getFindItemResponseMessageArray()[0];
        if (responseMessage.getResponseCode() != ResponseCodeType.NO_ERROR)
        {
            throw new FailedToFindMessage(
                    "ResponseCode some sort of error: " + responseMessage.getResponseCode());
        }
        for (MessageType email : responseMessage.getRootFolder().getItems().getMessageArray())
        {
            String folderId = RequiredEmail.getFolderId(email.getSubject());
            if (folderId != null)
            {
                List<MessageId> emails = emailResults.get(folderId);
                if (emails == null)
                {
                    emails = new ArrayList<MessageId>();
                    emailResults.put(folderId, emails);
                }
                emails.add(new MessageId(email.getItemId().getId(), email.getItemId().getChangeKey()));
            }
        }
        return emailResults;
    }

    private void moveMessages(final String user, final TargetFolderIdType targetFolderId,
                              final List<MessageId> messageIds) throws FailedToMoveMessage
    {
        EnvelopeDocument request = createEmptyRequest(user);
        MoveItemType moveItem = request.getEnvelope().addNewBody().addNewMoveItem();
        moveItem.setToFolderId(targetFolderId);
        NonEmptyArrayOfBaseItemIdsType itemIds = moveItem.addNewItemIds();
        for (MessageId messageId : messageIds)
        {
            ItemIdType itemId = itemIds.addNewItemId();
            itemId.setId(messageId.getId());
            itemId.setChangeKey(messageId.getChangeKey());
        }
        BodyType response = sendRequest(request);
        ItemInfoResponseMessageType[] responses =
                response.getMoveItemResponse().getResponseMessages().getMoveItemResponseMessageArray();
        if (responses.length != messageIds.size())
        {
            throw new FailedToMoveMessage("There should have been 1 response message to moveItem");
        }

        for (ItemInfoResponseMessageType resp : responses)
        {
            if (resp.getResponseCode() != ResponseCodeType.NO_ERROR)
            {
                throw new FailedToMoveMessage("ResponseCode some sort of error: " + resp.getResponseCode());
            }
        }
    }

    public void moveMessages(final String user, final String folder, final List<MessageId> messageIds)
            throws FailedToMoveMessage
    {
        TargetFolderIdType targetFolderId = TargetFolderIdType.Factory.newInstance();
        targetFolderId.addNewFolderId().setId(folder);
        moveMessages(user, targetFolderId, messageIds);
    }

    public void moveMessages(final String user, final DistinguishedFolderIdNameType.Enum distinguishedFolder,
                             final List<MessageId> messageIds) throws FailedToMoveMessage
    {
        TargetFolderIdType targetFolderId = TargetFolderIdType.Factory.newInstance();
        targetFolderId.addNewDistinguishedFolderId().setId(distinguishedFolder);
        moveMessages(user, targetFolderId, messageIds);
    }

    private BodyType sendRequest(final EnvelopeDocument envelope) throws SendRequestFailed
    {
        String request = DECLARATION + envelope.xmlText();

        LOG.trace("Sending SOAP request to {}.  SOAP envelope:", endpoint);
        LOG.trace(envelope.toString());

        try
        {
            HttpURLConnection conn = connectionFactory.newInstance(endpoint, request.getBytes(SOAP_ENCODING));

            int code = conn.getResponseCode();

            InputStream responseData = conn.getInputStream();

            int amtAvailable = responseData.available();

            if (code == HttpURLConnection.HTTP_OK)
            {
                EnvelopeDocument response = EnvelopeDocument.Factory.parse(responseData);

                LOG.trace("SOAP response received from {}.  SOAP envelope:", endpoint);
                LOG.trace(response.toString());

                return response.getEnvelope().getBody();
            }
            else
            {
                LOG.debug("HTTP Error: {}", code);
                throw new HttpErrorException(code);
            }
        }
        catch (Exception e)
        {
            throw new SendRequestFailed("Unexpected Exception: " + e.getMessage(), e);
        }

    }

    /** Exception for when sending a request to exchange fails. */
    public class SendRequestFailed extends RuntimeException
    {
        public SendRequestFailed(final String message, final Throwable cause)
        {
            super(message, cause);
        }
    }

    /** Exception for when creating folders fails. */
    public class FailedToCreateFolders extends Exception
    {
        public FailedToCreateFolders(final String message)
        {
            super(message);
        }
    }

    /** Exception for when creating messages fails. */
    public class FailedToCreateMessage extends Exception
    {
        public FailedToCreateMessage(final String message)
        {
            super(message);
        }
    }

    /** Exception for when deleting messages fails. */
    public class FailedToDeleteMessage extends Exception
    {
        public FailedToDeleteMessage(final String message)
        {
            super(message);
        }
    }

    /** Exception for when finding messages fails. */
    public class FailedToFindMessage extends Exception
    {
        public FailedToFindMessage(final String message)
        {
            super(message);
        }
    }

    /** Exception for when moving messages fails. */
    public class FailedToMoveMessage extends Exception
    {
        public FailedToMoveMessage(final String message)
        {
            super(message);
        }
    }


    /** A simple class representing an email. */
    public final class MessageId
    {
        private final String id;
        private final String changeKey;

        private MessageId(final String messageId, final String messageChangeKey)
        {
            id = messageId;
            changeKey = messageChangeKey;
        }

        private String getId()
        {
            return id;
        }

        private String getChangeKey()
        {
            return changeKey;
        }

        @Override
        public String toString()
        {
            return "MessageId{"
                   + "id='" + id + '\''
                   + ", changeKey='" + changeKey + '\''
                   + '}';
        }
    }
}
TOP

Related Classes of com.ripariandata.timberwolf.mail.exchange.ExchangePump$MessageId

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.