/** * Copyright (c) 2011-2013 Optimax Software Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Optimax Software, ElasticInbox, nor the names * of its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.elasticinbox.pop3.server.handler; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import org.apache.james.protocols.pop3.mailbox.MessageMetaData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.elasticinbox.common.utils.CRLFInputStream; import com.elasticinbox.core.MessageDAO; import com.elasticinbox.core.MessageModification; import com.elasticinbox.core.model.Mailbox; import com.elasticinbox.core.model.Message; import com.elasticinbox.core.model.ReservedLabels; import com.elasticinbox.core.utils.Base64UUIDUtils; /** * POP3 Mailbox implementation * * @author Rustam Aliyev */ public class ElasticInboxMailboxHandler implements org.apache.james.protocols.pop3.mailbox.Mailbox { private static final Logger logger = LoggerFactory.getLogger(ElasticInboxMailboxHandler.class); private final static int MAX_POP3_SESSION_MESSAGES = 300; private final Mailbox mailbox; private final MessageDAO dao; private List<MessageMetaData> messageList; public ElasticInboxMailboxHandler(final MessageDAO dao, final Mailbox mailbox) { // initialize DAO and Mailbox this.dao = dao; this.mailbox = mailbox; // initialize list of messages for the current session messageList = getPOP3MessageList(); logger.debug("Initialized new POP3 session for {}", mailbox); } @Override public InputStream getMessage(String uid) throws IOException { UUID uuid = Base64UUIDUtils.decode(uid); logger.debug("POP3: Get message {}/{} [{}]", mailbox, uuid, uid); try { InputStream is = dao.getRaw(mailbox, uuid).getUncompressedInputStream(); return new CRLFInputStream(is); } catch (Exception e) { logger.error("Error occured while retreiving POP3 message " + mailbox + "/" + uuid + " :", e); throw new IOException("Unable to read message"); } } @Override public List<MessageMetaData> getMessages() throws IOException { logger.debug("POP3: List messages for {}", mailbox); return messageList; } @Override public void remove(String... uids) throws IOException { logger.debug("POP3: Removing messages {} from {}", uids, mailbox); Set<Integer> labels = new HashSet<Integer>(1); labels.add(ReservedLabels.POP3.getId()); List<UUID> uuids = new ArrayList<UUID>(uids.length); for (String uid : uids) { uuids.add(Base64UUIDUtils.decode(uid)); } dao.modify(mailbox, uuids, new MessageModification.Builder().removeLabels(labels).build()); } @Override public String getIdentifier() throws IOException { logger.debug("POP3: Get identifier"); return mailbox.toString(); } @Override public void close() throws IOException { logger.debug("POP3: Close"); } @Override public InputStream getMessageBody(String uid) throws IOException { // should never be called throw new IOException("Not implemented"); } @Override public InputStream getMessageHeaders(String uid) throws IOException { // should never be called throw new IOException("Not implemented"); } /** * Initialise a list of messages visible for the current session * * @return List of messages */ private List<MessageMetaData> getPOP3MessageList() { // get list of messages Map<UUID, Message> messages = dao.getMessageIdsWithMetadata( mailbox, ReservedLabels.POP3.getId(), null, MAX_POP3_SESSION_MESSAGES, true, false); // convert to James Protocols list List<MessageMetaData> list = new ArrayList<MessageMetaData>(messages.size()); for (Map.Entry<UUID, Message> entry : messages.entrySet()) { MessageMetaData md = new MessageMetaData( Base64UUIDUtils.encode(entry.getKey()), entry.getValue().getSize()); list.add(md); } return list; } }