You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by no...@apache.org on 2010/06/04 15:07:08 UTC
svn commit: r951398 [3/4] - in /james/imap/trunk:
deployment/src/test/java/org/apache/james/imap/functional/inmemory/
deployment/src/test/java/org/apache/james/imap/functional/jcr/
deployment/src/test/java/org/apache/james/imap/functional/jpa/ jcr/src/...
Added: james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/user/model/InMemorySubscription.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/user/model/InMemorySubscription.java?rev=951398&view=auto
==============================================================================
--- james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/user/model/InMemorySubscription.java (added)
+++ james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/user/model/InMemorySubscription.java Fri Jun 4 13:07:05 2010
@@ -0,0 +1,87 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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 org.apache.james.imap.inmemory.user.model;
+
+import org.apache.james.imap.mailbox.MailboxSession.User;
+import org.apache.james.imap.store.user.model.Subscription;
+
+public class InMemorySubscription implements Subscription {
+
+ private final String mailbox;
+ private final String user;
+
+ public InMemorySubscription(final String mailbox, final User user) {
+ super();
+ this.mailbox = mailbox;
+ this.user = user.getUserName();
+ }
+
+ public String getMailbox() {
+ return mailbox;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ result = PRIME * result + ((mailbox == null) ? 0 : mailbox.hashCode());
+ result = PRIME * result + ((user == null) ? 0 : user.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final InMemorySubscription other = (InMemorySubscription) obj;
+ if (mailbox == null) {
+ if (other.mailbox != null)
+ return false;
+ } else if (!mailbox.equals(other.mailbox))
+ return false;
+ if (user == null) {
+ if (other.user != null)
+ return false;
+ } else if (!user.equals(other.user))
+ return false;
+ return true;
+ }
+
+ /**
+ * Representation suitable for logging and debugging.
+ * @return a <code>String</code> representation
+ * of this object.
+ */
+ public String toString()
+ {
+ return "InMemorySubscription[ "
+ + "mailbox = " + this.mailbox + " "
+ + "user = " + this.user + " "
+ + " ]";
+ }
+
+}
Added: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/MailboxSessionMapperFactory.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/MailboxSessionMapperFactory.java?rev=951398&view=auto
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/MailboxSessionMapperFactory.java (added)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/MailboxSessionMapperFactory.java Fri Jun 4 13:07:05 2010
@@ -0,0 +1,132 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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 org.apache.james.imap.store;
+
+import org.apache.james.imap.mailbox.MailboxException;
+import org.apache.james.imap.mailbox.MailboxSession;
+import org.apache.james.imap.mailbox.SubscriptionException;
+import org.apache.james.imap.store.mail.MailboxMapper;
+import org.apache.james.imap.store.mail.MessageMapper;
+import org.apache.james.imap.store.user.SubscriptionMapper;
+
+/**
+ * Maintain mapper instances by {@link MailboxSession}. So only one mapper instance is used
+ * in a {@link MailboxSession}
+ */
+public abstract class MailboxSessionMapperFactory <Id> {
+
+ protected final static String MESSAGEMAPPER ="MESSAGEMAPPER";
+ protected final static String MAILBOXMAPPER ="MAILBOXMAPPER";
+ protected final static String SUBSCRIPTIONMAPPER ="SUBSCRIPTIONMAPPER";
+
+ /**
+ * Create a {@link MessageMapper} instance of return the one which exists for the {@link MailboxSession} already
+ *
+ * @param session
+ * @param mailboxId
+ * @return mapper
+ */
+ @SuppressWarnings("unchecked")
+ public MessageMapper<Id> getMessageMapper(MailboxSession session) throws MailboxException {
+ MessageMapper<Id> mapper = (MessageMapper<Id>) session.getAttributes().get(MESSAGEMAPPER);
+ if (mapper == null) {
+ mapper = createMessageMapper(session);
+ session.getAttributes().put(MESSAGEMAPPER, mapper);
+ }
+ return mapper;
+ }
+
+ /**
+ * Create a {@link MessageMapper} instance which will get reused during the whole {@link MailboxSession}
+ *
+ * @param session
+ * @return messageMapper
+ * @throws MailboxException
+ */
+ protected abstract MessageMapper<Id> createMessageMapper(MailboxSession session) throws MailboxException;
+
+ /**
+ * Create a {@link MailboxMapper} instance or return the one which exists for the {@link MailboxSession} already
+ *
+ * @param session
+ * @return mapper
+ */
+ @SuppressWarnings("unchecked")
+ public MailboxMapper<Id> getMailboxMapper(MailboxSession session) throws MailboxException {
+ MailboxMapper<Id> mapper = (MailboxMapper<Id>) session.getAttributes().get(MAILBOXMAPPER);
+ if (mapper == null) {
+ mapper = createMailboxMapper(session);
+ session.getAttributes().put(MAILBOXMAPPER, mapper);
+ }
+ return mapper;
+ }
+
+ /**
+ * Create a {@link MailboxMapper} instance which will get reused during the whole {@link MailboxSession}
+ *
+ * @param session
+ * @return mailboxMapper
+ * @throws MailboxException
+ */
+ protected abstract MailboxMapper<Id> createMailboxMapper(MailboxSession session) throws MailboxException;
+
+ /**
+ * Create a {@link SubscriptionMapper} instance or return the one which exists for the {@link MailboxSession} already
+ *
+ * @param session
+ * @return mapper
+ */
+ public SubscriptionMapper getSubscriptionMapper(MailboxSession session) throws SubscriptionException {
+ SubscriptionMapper mapper = (SubscriptionMapper) session.getAttributes().get(SUBSCRIPTIONMAPPER);
+ if (mapper == null) {
+ mapper = createSubscriptionMapper(session);
+ session.getAttributes().put(SUBSCRIPTIONMAPPER, mapper);
+ }
+ return mapper;
+ }
+
+ /**
+ * Create a {@link SubscriptionMapper} instance which will get reused during the whole {@link MailboxSession}
+ * @param session
+ * @return subscriptionMapper
+ * @throws SubscriptionException
+ */
+ protected abstract SubscriptionMapper createSubscriptionMapper(MailboxSession session) throws SubscriptionException;
+
+ /**
+ * Callback which needs to get called once an IMAP Request was complete. It will take care of getting rid of all Session-scoped stuff
+ *
+ * @param session
+ */
+ @SuppressWarnings("unchecked")
+ public void endRequest(MailboxSession session) {
+ if (session == null) return;
+ MessageMapper<Id> messageMapper = (MessageMapper) session.getAttributes().get(MESSAGEMAPPER);
+ MailboxMapper<Id> mailboxMapper = (MailboxMapper) session.getAttributes().get(MAILBOXMAPPER);
+ SubscriptionMapper subscriptionMapper = (SubscriptionMapper) session.getAttributes().get(SUBSCRIPTIONMAPPER);
+ if (messageMapper != null)
+ messageMapper.endRequest();
+ if (mailboxMapper != null)
+ mailboxMapper.endRequest();
+ if (subscriptionMapper != null)
+ subscriptionMapper.endRequest();
+ }
+
+
+}
Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/MimeDescriptorImpl.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/MimeDescriptorImpl.java?rev=951398&r1=951397&r2=951398&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/MimeDescriptorImpl.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/MimeDescriptorImpl.java Fri Jun 4 13:07:05 2010
@@ -33,6 +33,8 @@ import org.apache.james.imap.mailbox.Mim
import org.apache.james.imap.store.mail.model.Document;
import org.apache.james.imap.store.mail.model.Property;
import org.apache.james.imap.store.mail.model.PropertyBuilder;
+import org.apache.james.imap.store.streaming.ConfigurableMimeTokenStream;
+import org.apache.james.imap.store.streaming.CountingInputStream;
import org.apache.james.mime4j.MimeException;
import org.apache.james.mime4j.descriptor.MaximalBodyDescriptor;
import org.apache.james.mime4j.parser.MimeEntityConfig;
Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/PasswordAwareMailboxSession.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/PasswordAwareMailboxSession.java?rev=951398&r1=951397&r2=951398&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/PasswordAwareMailboxSession.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/PasswordAwareMailboxSession.java Fri Jun 4 13:07:05 2010
@@ -28,33 +28,35 @@ import org.apache.commons.logging.Log;
*
*
*/
-public class PasswordAwareMailboxSession extends SimpleMailboxSession implements PasswordAwareUser{
+// TODO: Why does a session implement a user? This is not needed, I think.
+public class PasswordAwareMailboxSession extends SimpleMailboxSession implements
+ PasswordAwareUser {
- private final String password;
+ private final String password;
- public PasswordAwareMailboxSession(long sessionId, String userName,String password,
- Log log, char deliminator, List<Locale> localePreferences) {
- super(sessionId, userName, log, deliminator, localePreferences);
- this.password = password;
- }
-
+ public PasswordAwareMailboxSession(long sessionId, String userName,
+ String password, Log log, char deliminator,
+ List<Locale> localePreferences) {
+ super(sessionId, userName, log, deliminator, localePreferences);
+ this.password = password;
+ }
- /**
- * Return the User which is bound the the MailboxSession. This User is in fact an
- * instance of PasswordAwareUser.
- *
- * return user
- */
- public User getUser() {
- return this;
- }
-
- /**
- * Return the Password for the logged in user
- *
- * @return password
- */
- public String getPassword() {
- return password;
- }
+ /**
+ * Return the User which is bound the the MailboxSession. This User is in
+ * fact an instance of PasswordAwareUser.
+ *
+ * return user
+ */
+ public User getUser() {
+ return this;
+ }
+
+ /**
+ * Return the Password for the logged in user
+ *
+ * @return password
+ */
+ public String getPassword() {
+ return password;
+ }
}
Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/PasswordAwareUser.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/PasswordAwareUser.java?rev=951398&r1=951397&r2=951398&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/PasswordAwareUser.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/PasswordAwareUser.java Fri Jun 4 13:07:05 2010
@@ -27,12 +27,12 @@ import org.apache.james.imap.mailbox.Mai
*/
public interface PasswordAwareUser extends MailboxSession.User {
- /**
- * Return the Password for the logged in user
- *
- * @return password
- */
- public String getPassword();
+ /**
+ * Return the Password for the logged in user
+ *
+ * @return password
+ */
+ public String getPassword();
}
Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/ResultUtils.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/ResultUtils.java?rev=951398&r1=951397&r2=951398&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/ResultUtils.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/ResultUtils.java Fri Jun 4 13:07:05 2010
@@ -40,6 +40,10 @@ import org.apache.james.imap.mailbox.Mes
import org.apache.james.imap.mailbox.util.MessageResultImpl;
import org.apache.james.imap.store.mail.model.Header;
import org.apache.james.imap.store.mail.model.MailboxMembership;
+import org.apache.james.imap.store.streaming.DelegatingRewindableInputStream;
+import org.apache.james.imap.store.streaming.InputStreamContent;
+import org.apache.james.imap.store.streaming.PartContentBuilder;
+import org.apache.james.imap.store.streaming.RewindableInputStream;
import org.apache.james.mime4j.MimeException;
/**
Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailboxManager.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailboxManager.java?rev=951398&r1=951397&r2=951398&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailboxManager.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailboxManager.java Fri Jun 4 13:07:05 2010
@@ -71,43 +71,36 @@ public abstract class StoreMailboxManage
private final Authenticator authenticator;
private final Subscriber subscriber;
private final char delimiter;
-
+ protected final MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory;
private UidConsumer<Id> consumer;
- public StoreMailboxManager(final Authenticator authenticator, final Subscriber subscriber, final UidConsumer<Id> consumer) {
- this(authenticator, subscriber, consumer, '.');
+ public StoreMailboxManager(MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory, final Authenticator authenticator, final Subscriber subscriber, final UidConsumer<Id> consumer) {
+ this(mailboxSessionMapperFactory, authenticator, subscriber, consumer, '.');
}
- public StoreMailboxManager(final Authenticator authenticator, final Subscriber subscriber, final UidConsumer<Id> consumer, final char delimiter) {
+ public StoreMailboxManager(MailboxSessionMapperFactory<Id> mailboxSessionMapperFactory, final Authenticator authenticator, final Subscriber subscriber, final UidConsumer<Id> consumer, final char delimiter) {
this.authenticator = authenticator;
this.subscriber = subscriber;
this.delimiter = delimiter;
this.consumer = consumer;
+ this.mailboxSessionMapperFactory = mailboxSessionMapperFactory;
}
-
/**
- * Create a StoreMailbox for the given Mailbox
+ * Create a {@link StoreMessageManager} for the given Mailbox
*
* @param mailboxRow
* @return storeMailbox
*/
- protected abstract StoreMessageManager<Id> createMailbox(MailboxEventDispatcher dispatcher, UidConsumer<Id> consumer, Mailbox<Id> mailboxRow, MailboxSession session) throws MailboxException;
-
- /**
- * Create the MailboxMapper
- *
- * @return mailboxMapper
- */
- protected abstract MailboxMapper<Id> createMailboxMapper(MailboxSession session) throws MailboxException;
-
+ protected abstract StoreMessageManager<Id> createMessageManager(MailboxEventDispatcher dispatcher, UidConsumer<Id> consumer, Mailbox<Id> mailboxRow, MailboxSession session) throws MailboxException;
+
/**
* Create a Mailbox for the given namespace and store it to the underlying storage
*
* @param namespaceName
* @throws MailboxException
*/
- protected abstract void doCreate(String namespaceName, MailboxSession session) throws MailboxException;
+ protected abstract void doCreateMailbox(String namespaceName, MailboxSession session) throws MailboxException;
/*
@@ -128,7 +121,7 @@ public abstract class StoreMailboxManage
*/
private StoreMessageManager<Id> doGetMailbox(String mailboxName, MailboxSession session) throws MailboxException {
synchronized (mutex) {
- final MailboxMapper<Id> mapper = createMailboxMapper(session);
+ final MailboxMapper<Id> mapper = mailboxSessionMapperFactory.getMailboxMapper(session);
Mailbox<Id> mailboxRow = mapper.findMailboxByName(mailboxName);
if (mailboxRow == null) {
@@ -138,7 +131,7 @@ public abstract class StoreMailboxManage
} else {
getLog().debug("Loaded mailbox " + mailboxName);
- StoreMessageManager<Id> result = createMailbox(dispatcher, consumer, mailboxRow, session);
+ StoreMessageManager<Id> result = createMessageManager(dispatcher, consumer, mailboxRow, session);
result.addListener(delegatingListener);
return result;
}
@@ -173,7 +166,7 @@ public abstract class StoreMailboxManage
final String mailbox = namespaceName
.substring(0, index);
if (!mailboxExists(mailbox, mailboxSession)) {
- doCreate(mailbox, mailboxSession);
+ doCreateMailbox(mailbox, mailboxSession);
}
}
index = namespaceName.indexOf(delimiter, ++index);
@@ -181,7 +174,7 @@ public abstract class StoreMailboxManage
if (mailboxExists(namespaceName, mailboxSession)) {
throw new MailboxExistsException(namespaceName);
} else {
- doCreate(namespaceName, mailboxSession);
+ doCreateMailbox(namespaceName, mailboxSession);
}
}
}
@@ -197,7 +190,7 @@ public abstract class StoreMailboxManage
synchronized (mutex) {
// TODO put this into a serilizable transaction
- final MailboxMapper<Id> mapper = createMailboxMapper(session);
+ final MailboxMapper<Id> mapper = mailboxSessionMapperFactory.getMailboxMapper(session);
mapper.execute(new TransactionalMapper.Transaction() {
@@ -228,7 +221,7 @@ public abstract class StoreMailboxManage
throw new MailboxExistsException(to);
}
- final MailboxMapper<Id> mapper = createMailboxMapper(session);
+ final MailboxMapper<Id> mapper = mailboxSessionMapperFactory.getMailboxMapper(session);
mapper.execute(new TransactionalMapper.Transaction() {
public void run() throws MailboxException {
@@ -314,7 +307,7 @@ public abstract class StoreMailboxManage
delimiter).replace(freeWildcard, SQL_WILDCARD_CHAR)
.replace(localWildcard, SQL_WILDCARD_CHAR);
- final MailboxMapper<Id> mapper = createMailboxMapper(session);
+ final MailboxMapper<Id> mapper = mailboxSessionMapperFactory.getMailboxMapper(session);
final List<Mailbox<Id>> mailboxes = mapper.findMailboxWithNameLike(search);
final List<MailboxMetaData> results = new ArrayList<MailboxMetaData>(mailboxes.size());
for (Mailbox<Id> mailbox: mailboxes) {
@@ -354,7 +347,7 @@ public abstract class StoreMailboxManage
*/
public boolean mailboxExists(String mailboxName, MailboxSession session) throws MailboxException {
synchronized (mutex) {
- final MailboxMapper<Id> mapper = createMailboxMapper(session);
+ final MailboxMapper<Id> mapper = mailboxSessionMapperFactory.getMailboxMapper(session);
final long count = mapper.countMailboxesWithName(mailboxName);
if (count == 0) {
return false;
@@ -497,11 +490,10 @@ public abstract class StoreMailboxManage
/**
- * End processing of Request for session. Default is to do nothing.
- * Implementations should override this if they need to do anything special
+ * End processing of Request for session
*/
public void endProcessingRequest(MailboxSession session) {
- // Default do nothing
+ mailboxSessionMapperFactory.endRequest(session);
}
Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMessageManager.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMessageManager.java?rev=951398&r1=951397&r2=951398&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMessageManager.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMessageManager.java Fri Jun 4 13:07:05 2010
@@ -52,12 +52,13 @@ import org.apache.james.imap.mailbox.Sea
import org.apache.james.imap.mailbox.MessageResult.FetchGroup;
import org.apache.james.imap.mailbox.util.MailboxEventDispatcher;
import org.apache.james.imap.mailbox.util.UidRange;
-import org.apache.james.imap.store.mail.MailboxMapper;
import org.apache.james.imap.store.mail.MessageMapper;
import org.apache.james.imap.store.mail.model.Header;
import org.apache.james.imap.store.mail.model.Mailbox;
import org.apache.james.imap.store.mail.model.MailboxMembership;
import org.apache.james.imap.store.mail.model.PropertyBuilder;
+import org.apache.james.imap.store.streaming.ConfigurableMimeTokenStream;
+import org.apache.james.imap.store.streaming.CountingInputStream;
import org.apache.james.imap.store.transaction.TransactionalMapper;
import org.apache.james.mime4j.MimeException;
import org.apache.james.mime4j.descriptor.MaximalBodyDescriptor;
@@ -78,18 +79,21 @@ public abstract class StoreMessageManage
private static final int INITIAL_SIZE_FLAGS = 32;
private static final int INITIAL_SIZE_HEADERS = 32;
+
+ private MessageMapper<Id> messageMapper;
- private final Id mailboxId;
+ private final Mailbox<Id> mailbox;
private MailboxEventDispatcher dispatcher;
private UidConsumer<Id> consumer;
- public StoreMessageManager(final MailboxEventDispatcher dispatcher, UidConsumer<Id> consumer, final Mailbox<Id> mailbox) {
- this.mailboxId = mailbox.getMailboxId();
+ public StoreMessageManager(MailboxSessionMapperFactory<Id> mapperFactory, final MailboxEventDispatcher dispatcher, UidConsumer<Id> consumer, final Mailbox<Id> mailbox, MailboxSession session) throws MailboxException {
+ this.mailbox = mailbox;
this.dispatcher = dispatcher;
this.consumer = consumer;
+ this.messageMapper = mapperFactory.getMessageMapper(session);
}
/**
@@ -111,14 +115,6 @@ public abstract class StoreMessageManage
protected abstract MailboxMembership<Id> copyMessage(MailboxMembership<Id> originalMessage, long uid, MailboxSession session) throws MailboxException;
/**
- * Create a new {@link MessageMapper} to use for the current Request.
- *
- * @return mapper
- */
- protected abstract MessageMapper<Id> createMessageMapper(MailboxSession session) throws MailboxException;
-
-
- /**
* Return the underlying {@link Mailbox}
*
* @param session
@@ -126,9 +122,8 @@ public abstract class StoreMessageManage
* @throws MailboxException
*/
- protected Mailbox<Id> getMailboxEntity(MailboxSession session) throws MailboxException {
- final MailboxMapper<Id> mapper = createMailboxMapper(session);
- return mapper.findMailboxById(getMailboxId());
+ public Mailbox<Id> getMailboxEntity() throws MailboxException {
+ return mailbox;
}
/**
@@ -137,7 +132,7 @@ public abstract class StoreMessageManage
* @return id
*/
protected Id getMailboxId() {
- return mailboxId;
+ return mailbox.getMailboxId();
}
/*
@@ -145,8 +140,7 @@ public abstract class StoreMessageManage
* @see org.apache.james.imap.mailbox.Mailbox#getMessageCount(org.apache.james.imap.mailbox.MailboxSession)
*/
public int getMessageCount(MailboxSession mailboxSession) throws MailboxException {
- final MessageMapper<Id> messageMapper = createMessageMapper(mailboxSession);
- return (int) messageMapper.countMessagesInMailbox();
+ return (int) messageMapper.countMessagesInMailbox(getMailboxId());
}
/*
@@ -157,10 +151,7 @@ public abstract class StoreMessageManage
final MailboxSession mailboxSession,final boolean isRecent, final Flags flagsToBeSet)
throws MailboxException {
// this will hold the uid after the transaction was complete
- final MessageMapper<Id> mapper = createMessageMapper(mailboxSession);
-
- final long uid = consumer.reserveNextUid(getMailboxEntity(mailboxSession), mailboxSession);
-
+ final long uid = consumer.reserveNextUid(getMailboxEntity(), mailboxSession);
File file = null;
try {
@@ -282,14 +273,14 @@ public abstract class StoreMessageManage
}
final MailboxMembership<Id> message = createMessage(internalDate, uid, size, bodyStartOctet, new FileInputStream(file), flags, headers, propertyBuilder);
- mapper.execute(new TransactionalMapper.Transaction() {
+ messageMapper.execute(new TransactionalMapper.Transaction() {
public void run() throws MailboxException {
- mapper.save(message);
+ messageMapper.save(getMailboxId(), message);
}
});
- dispatcher.added(uid, mailboxSession.getSessionId(), getMailboxEntity(mailboxSession).getName());
+ dispatcher.added(uid, mailboxSession.getSessionId(), getMailboxEntity().getName());
return uid;
} catch (IOException e) {
e.printStackTrace();
@@ -387,8 +378,7 @@ public abstract class StoreMessageManage
public Iterator<MessageResult> getMessages(final MessageRange set, FetchGroup fetchGroup,
MailboxSession mailboxSession) throws MailboxException {
UidRange range = uidRangeForMessageSet(set);
- final MessageMapper<Id> messageMapper = createMessageMapper(mailboxSession);
- final List<MailboxMembership<Id>> rows = new ArrayList<MailboxMembership<Id>>(messageMapper.findInMailbox(set));
+ final List<MailboxMembership<Id>> rows = new ArrayList<MailboxMembership<Id>>(messageMapper.findInMailbox(getMailboxId(), set));
return getMessages(fetchGroup, range, rows);
}
@@ -421,20 +411,19 @@ public abstract class StoreMessageManage
}
private long[] recent(final boolean reset, MailboxSession mailboxSession) throws MailboxException {
- final MessageMapper<Id> mapper = createMessageMapper(mailboxSession);
final List<Long> results = new ArrayList<Long>();
- mapper.execute(new TransactionalMapper.Transaction() {
+ messageMapper.execute(new TransactionalMapper.Transaction() {
public void run() throws MailboxException {
- final List<MailboxMembership<Id>> members = mapper.findRecentMessagesInMailbox();
+ final List<MailboxMembership<Id>> members = messageMapper.findRecentMessagesInMailbox(getMailboxId());
for (MailboxMembership<Id> member:members) {
results.add(member.getUid());
if (reset) {
member.unsetRecent();
}
- mapper.save(member);
+ messageMapper.save(getMailboxId(), member);
}
}
@@ -445,9 +434,7 @@ public abstract class StoreMessageManage
private Long getFirstUnseen(MailboxSession mailboxSession) throws MailboxException {
try {
- final MessageMapper<Id> messageMapper = createMessageMapper(mailboxSession);
-
- final List<MailboxMembership<Id>> members = messageMapper.findUnseenMessagesInMailbox();
+ final List<MailboxMembership<Id>> members = messageMapper.findUnseenMessagesInMailbox(getMailboxId());
final Iterator<MailboxMembership<Id>> it = members.iterator();
final Long result;
if (it.hasNext()) {
@@ -463,8 +450,7 @@ public abstract class StoreMessageManage
}
private int getUnseenCount(MailboxSession mailboxSession) throws MailboxException {
- final MessageMapper<Id> messageMapper = createMessageMapper(mailboxSession);
- final int count = (int) messageMapper.countUnseenMessagesInMailbox();
+ final int count = (int) messageMapper.countUnseenMessagesInMailbox(getMailboxId());
return count;
}
@@ -478,16 +464,15 @@ public abstract class StoreMessageManage
private Iterator<Long> doExpunge(final MessageRange set, MailboxSession mailboxSession)
throws MailboxException {
- final MessageMapper<Id> mapper = createMessageMapper(mailboxSession);
final Collection<Long> uids = new TreeSet<Long>();
- mapper.execute(new TransactionalMapper.Transaction() {
+ messageMapper.execute(new TransactionalMapper.Transaction() {
public void run() throws MailboxException {
- final List<MailboxMembership<Id>> members = mapper.findMarkedForDeletionInMailbox(set);
+ final List<MailboxMembership<Id>> members = messageMapper.findMarkedForDeletionInMailbox(getMailboxId(), set);
for (MailboxMembership<Id> message:members) {
uids.add(message.getUid());
- mapper.delete(message);
+ messageMapper.delete(getMailboxId(), message);
}
}
@@ -495,7 +480,7 @@ public abstract class StoreMessageManage
Iterator<Long> uidIt = uids.iterator();
while(uidIt.hasNext()) {
- dispatcher.expunged(uidIt.next(), mailboxSession.getSessionId(), getMailboxEntity(mailboxSession).getName());
+ dispatcher.expunged(uidIt.next(), mailboxSession.getSessionId(), getMailboxEntity().getName());
}
return uids.iterator();
}
@@ -511,13 +496,12 @@ public abstract class StoreMessageManage
private Map<Long, Flags> doSetFlags(final Flags flags, final boolean value, final boolean replace,
final MessageRange set, final MailboxSession mailboxSession) throws MailboxException {
- final MessageMapper<Id> mapper = createMessageMapper(mailboxSession);
final SortedMap<Long, Flags> newFlagsByUid = new TreeMap<Long, Flags>();
final Map<Long, Flags> originalFlagsByUid = new HashMap<Long, Flags>(INITIAL_SIZE_FLAGS);
- mapper.execute(new TransactionalMapper.Transaction(){
+ messageMapper.execute(new TransactionalMapper.Transaction(){
public void run() throws MailboxException {
- final List<MailboxMembership<Id>> members = mapper.findInMailbox(set);
+ final List<MailboxMembership<Id>> members = messageMapper.findInMailbox(getMailboxId(), set);
for (final MailboxMembership<Id> member:members) {
originalFlagsByUid.put(member.getUid(), member.createFlags());
if (replace) {
@@ -532,7 +516,7 @@ public abstract class StoreMessageManage
member.setFlags(current);
}
newFlagsByUid.put(member.getUid(), member.createFlags());
- mapper.save(member);
+ messageMapper.save(getMailboxId(), member);
}
}
@@ -541,7 +525,7 @@ public abstract class StoreMessageManage
Iterator<Long> it = newFlagsByUid.keySet().iterator();
while (it.hasNext()) {
Long uid = it.next();
- dispatcher.flagsUpdated(uid, mailboxSession.getSessionId(), getMailboxEntity(mailboxSession).getName(), originalFlagsByUid.get(uid), newFlagsByUid.get(uid));
+ dispatcher.flagsUpdated(uid, mailboxSession.getSessionId(), getMailboxEntity().getName(), originalFlagsByUid.get(uid), newFlagsByUid.get(uid));
}
return newFlagsByUid;
@@ -552,12 +536,12 @@ public abstract class StoreMessageManage
}
private long getUidValidity(MailboxSession mailboxSession) throws MailboxException {
- final long result = getMailboxEntity(mailboxSession).getUidValidity();
+ final long result = getMailboxEntity().getUidValidity();
return result;
}
private long getUidNext(MailboxSession mailboxSession) throws MailboxException {
- Mailbox<Id> mailbox = getMailboxEntity(mailboxSession);
+ Mailbox<Id> mailbox = getMailboxEntity();
if (mailbox == null) {
throw new MailboxNotFoundException("Mailbox has been deleted");
} else {
@@ -571,8 +555,7 @@ public abstract class StoreMessageManage
* @see org.apache.james.imap.mailbox.Mailbox#search(org.apache.james.imap.mailbox.SearchQuery, org.apache.james.imap.mailbox.MailboxSession)
*/
public Iterator<Long> search(SearchQuery query, MailboxSession mailboxSession) throws MailboxException {
- final MessageMapper<Id> messageMapper = createMessageMapper(mailboxSession);
- final List<MailboxMembership<Id>> members = messageMapper.searchMailbox(query);
+ final List<MailboxMembership<Id>> members = messageMapper.searchMailbox(getMailboxId(), query);
final Set<Long> uids = new TreeSet<Long>();
for (MailboxMembership<Id> member:members) {
try {
@@ -594,46 +577,33 @@ public abstract class StoreMessageManage
return uids.iterator();
}
-
/**
* This mailbox is writable
*/
public boolean isWriteable() {
return true;
}
-
private void copy(final List<MailboxMembership<Id>> originalRows, final MailboxSession session) throws MailboxException {
try {
final List<MailboxMembership<Id>> copiedRows = new ArrayList<MailboxMembership<Id>>();
- final MessageMapper<Id> mapper = createMessageMapper(session);
-
for (final MailboxMembership<Id> originalMessage:originalRows) {
- final long uid = consumer.reserveNextUid(getMailboxEntity(session),session);
-
- mapper.execute(new TransactionalMapper.Transaction() {
+ final long uid = consumer.reserveNextUid(getMailboxEntity(),session);
+ messageMapper.execute(new TransactionalMapper.Transaction() {
public void run() throws MailboxException {
final MailboxMembership<Id> newRow = copyMessage(originalMessage, uid, session);
- mapper.save(newRow);
+ messageMapper.save(getMailboxId(), newRow);
copiedRows.add(newRow);
-
}
});
-
-
- }
-
-
-
-
+ }
// Wait until commit before issuing events
for (MailboxMembership<Id> newMember:copiedRows) {
- dispatcher.added(newMember.getUid(), session.getSessionId(), getMailboxEntity(session).getName());
+ dispatcher.added(newMember.getUid(), session.getSessionId(), getMailboxEntity().getName());
}
-
} catch (MessagingException e) {
throw new MailboxException(HumanReadableText.FAILURE_MAIL_PARSE, e);
}
@@ -649,9 +619,7 @@ public abstract class StoreMessageManage
*/
public void copyTo(MessageRange set, StoreMessageManager<Id> toMailbox, MailboxSession session) throws MailboxException {
try {
- final MessageMapper<Id> mapper = createMessageMapper(session);
-
- final List<MailboxMembership<Id>> originalRows = mapper.findInMailbox(set);
+ final List<MailboxMembership<Id>> originalRows = messageMapper.findInMailbox(getMailboxId(), set);
toMailbox.copy(originalRows, session);
} catch (MessagingException e) {
@@ -686,17 +654,7 @@ public abstract class StoreMessageManage
unseenCount = 0;
break;
}
-
return new MailboxMetaData(recent, permanentFlags, uidValidity, uidNext, messageCount, unseenCount, firstUnseen, isWriteable());
}
-
-
- /**
- * Create MailboxMapper
- *
- * @return mapper
- */
- protected abstract MailboxMapper<Id> createMailboxMapper(MailboxSession session) throws MailboxException;
-
-}
+}
\ No newline at end of file
Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreSubscriptionManager.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreSubscriptionManager.java?rev=951398&r1=951397&r2=951398&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreSubscriptionManager.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreSubscriptionManager.java Fri Jun 4 13:07:05 2010
@@ -32,28 +32,22 @@ import org.apache.james.imap.store.user.
/**
* Manages subscriptions.
*/
-public abstract class StoreSubscriptionManager implements Subscriber {
+public abstract class StoreSubscriptionManager<Id> implements Subscriber {
private static final int INITIAL_SIZE = 32;
- public StoreSubscriptionManager() {
- super();
- }
-
- /**
- * Create the SubscriptionMapper to use
- *
- * @return mapper
- */
- protected abstract SubscriptionMapper createMapper(MailboxSession session) throws SubscriptionException;
+ protected MailboxSessionMapperFactory<Id> mapperFactory;
+ public StoreSubscriptionManager(final MailboxSessionMapperFactory<Id> mapperFactory) {
+ this.mapperFactory = mapperFactory;
+ }
/*
* (non-Javadoc)
* @see org.apache.james.imap.store.Subscriber#subscribe(org.apache.james.imap.mailbox.MailboxSession, java.lang.String)
*/
public void subscribe(final MailboxSession session, final String mailbox) throws SubscriptionException {
- final SubscriptionMapper mapper = createMapper(session);
+ final SubscriptionMapper mapper = mapperFactory.getSubscriptionMapper(session);
try {
mapper.execute(new TransactionalMapper.Transaction() {
@@ -69,8 +63,6 @@ public abstract class StoreSubscriptionM
} catch (MailboxException e) {
throw new SubscriptionException(e.getKey(), e);
}
-
-
}
/**
@@ -80,14 +72,14 @@ public abstract class StoreSubscriptionM
* @param mailbox
* @return subscription
*/
- protected abstract Subscription createSubscription(final MailboxSession sonessi, final String mailbox);
+ protected abstract Subscription createSubscription(final MailboxSession session, final String mailbox);
/*
* (non-Javadoc)
* @see org.apache.james.imap.store.Subscriber#subscriptions(org.apache.james.imap.mailbox.MailboxSession)
*/
public Collection<String> subscriptions(final MailboxSession session) throws SubscriptionException {
- final SubscriptionMapper mapper = createMapper(session);
+ final SubscriptionMapper mapper = mapperFactory.getSubscriptionMapper(session);
final List<Subscription> subscriptions = mapper.findSubscriptionsForUser(session.getUser().getUserName());
final Collection<String> results = new HashSet<String>(INITIAL_SIZE);
for (Subscription subscription:subscriptions) {
@@ -101,7 +93,7 @@ public abstract class StoreSubscriptionM
* @see org.apache.james.imap.store.Subscriber#unsubscribe(java.lang.String, java.lang.String)
*/
public void unsubscribe(final MailboxSession session, final String mailbox) throws SubscriptionException {
- final SubscriptionMapper mapper = createMapper(session);
+ final SubscriptionMapper mapper = mapperFactory.getSubscriptionMapper(session);
try {
mapper.execute(new TransactionalMapper.Transaction() {
Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/MailboxMapper.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/MailboxMapper.java?rev=951398&r1=951397&r2=951398&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/MailboxMapper.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/MailboxMapper.java Fri Jun 4 13:07:05 2010
@@ -30,7 +30,7 @@ import org.apache.james.imap.store.trans
* to the end of the request.
*
*/
-public interface MailboxMapper<Id> extends TransactionalMapper{
+public interface MailboxMapper<Id> extends TransactionalMapper {
/**
* Save the give {@link Mailbox} to the underlying storage
Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/MessageMapper.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/MessageMapper.java?rev=951398&r1=951397&r2=951398&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/MessageMapper.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/MessageMapper.java Fri Jun 4 13:07:05 2010
@@ -42,7 +42,7 @@ public interface MessageMapper<Id> exten
* @return list
* @throws StorageException
*/
- public abstract List<MailboxMembership<Id>> findInMailbox(MessageRange set)
+ public abstract List<MailboxMembership<Id>> findInMailbox(Id mailboxId, MessageRange set)
throws StorageException;
/**
@@ -53,7 +53,7 @@ public interface MessageMapper<Id> exten
* @throws StorageException
*/
public abstract List<MailboxMembership<Id>> findMarkedForDeletionInMailbox(
- final MessageRange set)
+ Id mailboxId, final MessageRange set)
throws StorageException;
/**
@@ -62,7 +62,7 @@ public interface MessageMapper<Id> exten
* @return count
* @throws StorageException
*/
- public abstract long countMessagesInMailbox()
+ public abstract long countMessagesInMailbox(Id mailboxId)
throws StorageException;
/**
@@ -71,7 +71,7 @@ public interface MessageMapper<Id> exten
* @return unseenCount
* @throws StorageException
*/
- public abstract long countUnseenMessagesInMailbox()
+ public abstract long countUnseenMessagesInMailbox(Id mailboxId)
throws StorageException;
/**
@@ -81,7 +81,7 @@ public interface MessageMapper<Id> exten
* @return
* @throws StorageException
*/
- public abstract List<MailboxMembership<Id>> searchMailbox(SearchQuery query) throws StorageException;
+ public abstract List<MailboxMembership<Id>> searchMailbox(Id mailboxId, SearchQuery query) throws StorageException;
/**
* Delete the given {@link MailboxMembership}
@@ -89,7 +89,7 @@ public interface MessageMapper<Id> exten
* @param message
* @throws StorageException
*/
- public abstract void delete(MailboxMembership<Id> message) throws StorageException;
+ public abstract void delete(Id mailboxId, MailboxMembership<Id> message) throws StorageException;
/**
* Return a List of {@link MailboxMembership} which are unseen.
@@ -98,7 +98,7 @@ public interface MessageMapper<Id> exten
* @return list
* @throws StorageException
*/
- public abstract List<MailboxMembership<Id>> findUnseenMessagesInMailbox() throws StorageException;
+ public abstract List<MailboxMembership<Id>> findUnseenMessagesInMailbox(Id mailboxId) throws StorageException;
/**
* Return a List of {@link MailboxMembership} which are recent.
@@ -107,7 +107,7 @@ public interface MessageMapper<Id> exten
* @return recentList
* @throws StorageException
*/
- public abstract List<MailboxMembership<Id>> findRecentMessagesInMailbox() throws StorageException;
+ public abstract List<MailboxMembership<Id>> findRecentMessagesInMailbox(Id mailboxId) throws StorageException;
/**
@@ -116,6 +116,6 @@ public interface MessageMapper<Id> exten
* @param message
* @throws StorageException
*/
- public abstract void save(MailboxMembership<Id> message) throws StorageException;
+ public abstract void save(Id mailboxId, MailboxMembership<Id> message) throws StorageException;
}
\ No newline at end of file
Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/model/AbstractDocument.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/model/AbstractDocument.java?rev=951398&r1=951397&r2=951398&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/model/AbstractDocument.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/model/AbstractDocument.java Fri Jun 4 13:07:05 2010
@@ -21,9 +21,9 @@ package org.apache.james.imap.store.mail
import java.io.IOException;
import java.io.InputStream;
-import org.apache.james.imap.store.DelegatingRewindableInputStream;
-import org.apache.james.imap.store.LazySkippingInputStream;
-import org.apache.james.imap.store.RewindableInputStream;
+import org.apache.james.imap.store.streaming.DelegatingRewindableInputStream;
+import org.apache.james.imap.store.streaming.LazySkippingInputStream;
+import org.apache.james.imap.store.streaming.RewindableInputStream;
/**
Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/model/Document.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/model/Document.java?rev=951398&r1=951397&r2=951398&view=diff
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/model/Document.java (original)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/mail/model/Document.java Fri Jun 4 13:07:05 2010
@@ -21,7 +21,7 @@ package org.apache.james.imap.store.mail
import java.io.IOException;
import java.util.List;
-import org.apache.james.imap.store.RewindableInputStream;
+import org.apache.james.imap.store.streaming.RewindableInputStream;
/**
* A MIME documents, consisting of meta-data (including MIME headers)
Added: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/AbstractFullContent.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/AbstractFullContent.java?rev=951398&view=auto
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/AbstractFullContent.java (added)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/AbstractFullContent.java Fri Jun 4 13:07:05 2010
@@ -0,0 +1,111 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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 org.apache.james.imap.store.streaming;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.james.imap.mailbox.Content;
+import org.apache.james.imap.mailbox.MessageResult;
+import org.apache.james.imap.mailbox.MessageResult.Header;
+import org.apache.james.imap.store.ResultUtils;
+
+/**
+ * Abstract base class for {@link Content} implementations which hold the headers and
+ * the body a email
+ *
+ */
+public abstract class AbstractFullContent implements Content {
+
+
+ private List<Header> headers;
+
+ public AbstractFullContent(final List<MessageResult.Header> headers) throws IOException {
+ this.headers = headers;
+ }
+
+ protected long caculateSize() throws IOException{
+ long result = getBodySize();
+ result += 2;
+ for (final Iterator<MessageResult.Header> it = headers.iterator(); it.hasNext();) {
+ final MessageResult.Header header = it.next();
+ if (header != null) {
+ result += header.size();
+ result += 2;
+ }
+ }
+ return result;
+ }
+
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.mailbox.Content#writeTo(java.nio.channels.WritableByteChannel)
+ */
+ public final void writeTo(WritableByteChannel channel) throws IOException {
+ ByteBuffer newLine = ByteBuffer.wrap(ResultUtils.BYTES_NEW_LINE);
+ for (final Iterator<MessageResult.Header> it = headers.iterator(); it.hasNext();) {
+ final MessageResult.Header header = it.next();
+ if (header != null) {
+ header.writeTo(channel);
+ }
+ newLine.rewind();
+ writeAll(channel, newLine);
+ }
+ newLine.rewind();
+ writeAll(channel, newLine);
+ bodyWriteTo(channel);
+ }
+
+
+ /**
+ * Write all
+ *
+ * @param channel
+ * @param buffer
+ * @throws IOException
+ */
+ protected void writeAll(WritableByteChannel channel, ByteBuffer buffer)
+ throws IOException {
+ while (channel.write(buffer) > 0) {
+ // write more
+ }
+ }
+
+ /**
+ * Return the size of the body
+ *
+ * @return size
+ * @throws IOException
+ */
+ protected abstract long getBodySize() throws IOException;
+
+ /**
+ * Write the body to the channel
+ *
+ * @param channel
+ * @throws IOException
+ */
+ protected abstract void bodyWriteTo(WritableByteChannel channel) throws IOException;
+
+
+}
Added: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/AbstractRewindableInputStream.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/AbstractRewindableInputStream.java?rev=951398&view=auto
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/AbstractRewindableInputStream.java (added)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/AbstractRewindableInputStream.java Fri Jun 4 13:07:05 2010
@@ -0,0 +1,182 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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 org.apache.james.imap.store.streaming;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * {@link RewindableInputStream} which support the get rewinded. This is done by copy over every byte
+ * over to another {@link OutputStream}. What {@link OutputStream} to use is up to the implementations.
+ *
+ * The rewinding will get delayed as long as possible. So if you call
+ * rewind, it will only get performed when needed
+ *
+ * Be sure to call {@link #close()} once you done reading from the object. This will
+ * remove all temporary data
+ *
+ *
+ */
+public abstract class AbstractRewindableInputStream extends RewindableInputStream{
+
+ protected boolean end = false;
+
+ public AbstractRewindableInputStream(InputStream in) throws IOException {
+ super(in);
+ }
+
+ /**
+ * Return the OutputStream to which the data should get written when they are read the
+ * first time
+ *
+ * @return output
+ * @throws IOException
+ */
+ protected abstract OutputStream getRewindOutputStream() throws IOException;
+
+ /**
+ * Return the InputStream which should get used after the stream was rewinded
+ *
+ * @return rewindInput
+ * @throws IOException
+ */
+ protected abstract InputStream getRewindInputStream() throws IOException;
+
+ /**
+ * Dispose all temporary data
+ *
+ * @throws IOException
+ */
+ protected abstract void dispose() throws IOException;
+
+ /**
+ * Get called after the rewind was complete
+ *
+ * @throws IOException
+ */
+ protected abstract void afterRewindComplete() throws IOException;
+
+ /**
+ * Close the stream and dispose all temporary data
+ *
+ */
+ public void close() throws IOException {
+ try {
+ in.close();
+ OutputStream out = getRewindOutputStream();
+ if (out != null) {
+ out.close();
+ }
+ InputStream in = getRewindInputStream();
+ if (in != null) {
+ in.close();
+ }
+ } finally {
+ dispose();
+ }
+ }
+
+
+ /**
+ * Read data and write and store it for later usage once the rewind was done
+ */
+ @Override
+ public int read() throws IOException {
+ int i;
+ if (needsRewind()) {
+
+ rewindIfNeeded();
+ }
+
+ if (end == false) {
+ i = in.read();
+ if (i == -1) {
+ end = true;
+ } else {
+ getRewindOutputStream().write(i);
+ }
+ } else {
+ i = getRewindInputStream().read();
+ }
+ return i;
+ }
+
+ /**
+ * Read data and write and store it for later usage once the rewind was done
+ */
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (len == 0) {
+ return 0;
+ }
+ if (needsRewind()) {
+ rewindIfNeeded();
+ }
+
+ int i;
+ if (end == false) {
+ i = in.read(b, off, len);
+ if (i == -1) {
+ end = true;
+ }
+ getRewindOutputStream().write(b, off, len);
+ } else {
+ i = getRewindInputStream().read(b,off,len);
+ }
+ return i;
+ }
+
+ /**
+ * Read data and write and store it for later usage once the rewind was done
+ */
+ @Override
+ public void rewindIfNeeded() throws IOException {
+ if (needsRewind()) {
+ rewindDone();
+
+ if (end == false) {
+ while ( read() != -1);
+ }
+ // we don't need the original InputStream anymore so close it
+ in.close();
+ afterRewindComplete();
+ }
+ }
+
+ @Override
+ public int available() throws IOException {
+ if (end == false) {
+ return in.available();
+ } else {
+ return getRewindInputStream().available();
+ }
+ }
+
+ @Override
+ public long skip(long n) throws IOException {
+ for (int i = 0; i < n; i++) {
+ if (read() == -1) {
+ return n -i;
+ }
+ if (end) break;
+ }
+ return 0;
+ }
+}
Added: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/ByteContent.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/ByteContent.java?rev=951398&view=auto
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/ByteContent.java (added)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/ByteContent.java Fri Jun 4 13:07:05 2010
@@ -0,0 +1,60 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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 org.apache.james.imap.store.streaming;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+
+import org.apache.james.imap.mailbox.Content;
+
+public final class ByteContent implements Content {
+
+ private final ByteBuffer contents;
+
+ private final long size;
+
+ public ByteContent(final ByteBuffer contents) {
+ this.contents = contents;
+ size = contents.limit();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.mailbox.Content#size()
+ */
+ public long size() {
+ return size;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.mailbox.Content#writeTo(java.nio.channels.WritableByteChannel)
+ */
+ public void writeTo(WritableByteChannel channel) throws IOException {
+ contents.rewind();
+ while (channel.write(contents) > 0) {
+ // write more
+ }
+ }
+}
Added: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/CRLFOutputStream.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/CRLFOutputStream.java?rev=951398&view=auto
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/CRLFOutputStream.java (added)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/CRLFOutputStream.java Fri Jun 4 13:07:05 2010
@@ -0,0 +1,161 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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 org.apache.james.imap.store.streaming;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A Filter for use with SMTP or other protocols in which lines must end with
+ * CRLF. Converts every "isolated" occourency of \r or \n with \r\n
+ *
+ * RFC 2821 #2.3.7 mandates that line termination is CRLF, and that CR and LF
+ * must not be transmitted except in that pairing. If we get a naked LF, convert
+ * to CRLF.
+ *
+ */
+public class CRLFOutputStream extends FilterOutputStream {
+
+ /**
+ * Counter for number of last (0A or 0D).
+ */
+ protected int statusLast;
+
+ protected final static int LAST_WAS_OTHER = 0;
+
+ protected final static int LAST_WAS_CR = 1;
+
+ protected final static int LAST_WAS_LF = 2;
+
+ protected boolean startOfLine = true;
+
+ /**
+ * Constructor that wraps an OutputStream.
+ *
+ * @param out
+ * the OutputStream to be wrapped
+ */
+ public CRLFOutputStream(OutputStream out) {
+ super(out);
+ statusLast = LAST_WAS_LF; // we already assume a CRLF at beginning
+ // (otherwise TOP would not work correctly
+ // !)
+ }
+
+ /**
+ * Writes a byte to the stream Fixes any naked CR or LF to the RFC 2821
+ * mandated CFLF pairing.
+ *
+ * @param b
+ * the byte to write
+ *
+ * @throws IOException
+ * if an error occurs writing the byte
+ */
+ public void write(int b) throws IOException {
+ switch (b) {
+ case '\r':
+ out.write('\r');
+ out.write('\n');
+ startOfLine = true;
+ statusLast = LAST_WAS_CR;
+ break;
+ case '\n':
+ if (statusLast != LAST_WAS_CR) {
+ out.write('\r');
+ out.write('\n');
+ startOfLine = true;
+ }
+ statusLast = LAST_WAS_LF;
+ break;
+ default:
+ // we're no longer at the start of a line
+ out.write(b);
+ startOfLine = false;
+ statusLast = LAST_WAS_OTHER;
+ break;
+ }
+ }
+
+ /**
+ * Provides an extension point for ExtraDotOutputStream to be able to add
+ * dots at the beginning of new lines.
+ *
+ * @see java.io.FilterOutputStream#write(byte[], int, int)
+ */
+ protected void writeChunk(byte buffer[], int offset, int length)
+ throws IOException {
+ out.write(buffer, offset, length);
+ }
+
+ /**
+ * @see java.io.FilterOutputStream#write(byte[], int, int)
+ */
+ public synchronized void write(byte buffer[], int offset, int length)
+ throws IOException {
+ /* optimized */
+ int lineStart = offset;
+ for (int i = offset; i < length + offset; i++) {
+ switch (buffer[i]) {
+ case '\r':
+ // CR case. Write down the last line
+ // and position the new lineStart at the next char
+ writeChunk(buffer, lineStart, i - lineStart);
+ out.write('\r');
+ out.write('\n');
+ startOfLine = true;
+ lineStart = i + 1;
+ statusLast = LAST_WAS_CR;
+ break;
+ case '\n':
+ if (statusLast != LAST_WAS_CR) {
+ writeChunk(buffer, lineStart, i - lineStart);
+ out.write('\r');
+ out.write('\n');
+ startOfLine = true;
+ }
+ lineStart = i + 1;
+ statusLast = LAST_WAS_LF;
+ break;
+ default:
+ statusLast = LAST_WAS_OTHER;
+ }
+ }
+ if (length + offset > lineStart) {
+ writeChunk(buffer, lineStart, length + offset - lineStart);
+ startOfLine = false;
+ }
+ }
+
+ /**
+ * Ensure that the stream is CRLF terminated.
+ *
+ * @throws IOException
+ * if an error occurs writing the byte
+ */
+ public void checkCRLFTerminator() throws IOException {
+ if (statusLast == LAST_WAS_OTHER) {
+ out.write('\r');
+ out.write('\n');
+ statusLast = LAST_WAS_CR;
+ }
+ }
+}
Added: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/ConfigurableMimeTokenStream.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/ConfigurableMimeTokenStream.java?rev=951398&view=auto
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/ConfigurableMimeTokenStream.java (added)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/ConfigurableMimeTokenStream.java Fri Jun 4 13:07:05 2010
@@ -0,0 +1,29 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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 org.apache.james.imap.store.streaming;
+
+import org.apache.james.mime4j.parser.MimeEntityConfig;
+import org.apache.james.mime4j.parser.MimeTokenStream;
+
+public class ConfigurableMimeTokenStream extends MimeTokenStream {
+
+ public ConfigurableMimeTokenStream(MimeEntityConfig config) {
+ super(config);
+ }
+}
Added: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/CountingInputStream.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/CountingInputStream.java?rev=951398&view=auto
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/CountingInputStream.java (added)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/CountingInputStream.java Fri Jun 4 13:07:05 2010
@@ -0,0 +1,86 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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 org.apache.james.imap.store.streaming;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * {@link InputStream} implementation which just consume the the wrapped {@link InputStream} and count
+ * the lines which are contained within the wrapped stream
+ *
+ *
+ */
+final public class CountingInputStream extends InputStream {
+
+ private final InputStream in;
+
+ private int lineCount;
+
+ private int octetCount;
+
+ public CountingInputStream(InputStream in) {
+ super();
+ this.in = in;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.io.InputStream#read()
+ */
+ public int read() throws IOException {
+ int next = in.read();
+ if (next > 0) {
+ octetCount++;
+ if (next == '\r') {
+ lineCount++;
+ }
+ }
+ return next;
+ }
+
+ /**
+ * Return the line count
+ *
+ * @return lineCount
+ */
+ public final int getLineCount() {
+ return lineCount;
+ }
+
+ /**
+ * Return the octet count
+ *
+ * @return octetCount
+ */
+ public final int getOctetCount() {
+ return octetCount;
+ }
+
+ /**
+ * Reads - and discards - the rest of the stream
+ * @throws IOException
+ */
+ public void readAll() throws IOException {
+ while (read()>0);
+ }
+}
Added: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/DelegatingRewindableInputStream.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/DelegatingRewindableInputStream.java?rev=951398&view=auto
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/DelegatingRewindableInputStream.java (added)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/DelegatingRewindableInputStream.java Fri Jun 4 13:07:05 2010
@@ -0,0 +1,98 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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 org.apache.james.imap.store.streaming;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * {@link RewindableInputStream} implementation which just delegate the calls to {@link FileRewindableInputStream}
+ * or {@link InMemoryRewindableInputStream} depending on the size
+ *
+ *
+ */
+public class DelegatingRewindableInputStream extends RewindableInputStream{
+
+ public final static long MAX_INMEMORY_SIZE= 524288;
+
+ public DelegatingRewindableInputStream(InputStream in, long size, long maxInmemorySize) throws IOException {
+ super(null);
+ if (size > maxInmemorySize) {
+ this.in = new FileRewindableInputStream(in);
+ } else {
+ this.in = new InMemoryRewindableInputStream(in);
+
+ }
+ }
+
+ public DelegatingRewindableInputStream(InputStream in, long size) throws IOException {
+ this(in, size, MAX_INMEMORY_SIZE);
+ }
+
+ @Override
+ public int available() throws IOException {
+ return in.available();
+ }
+
+ @Override
+ public void close() throws IOException {
+ in.close();
+ }
+
+ @Override
+ public synchronized void mark(int readlimit) {
+ in.mark(readlimit);
+ }
+
+ @Override
+ public boolean markSupported() {
+ return in.markSupported();
+ }
+
+ @Override
+ public int read() throws IOException {
+ return in.read();
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ return in.read(b, off, len);
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ return in.read(b);
+ }
+
+ @Override
+ public synchronized void reset() throws IOException {
+ in.reset();
+ }
+
+ @Override
+ public long skip(long n) throws IOException {
+ return in.skip(n);
+ }
+
+ @Override
+ protected void rewindIfNeeded() throws IOException {
+ ((RewindableInputStream)in).rewindIfNeeded();
+ }
+
+}
Added: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/FileRewindableInputStream.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/FileRewindableInputStream.java?rev=951398&view=auto
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/FileRewindableInputStream.java (added)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/FileRewindableInputStream.java Fri Jun 4 13:07:05 2010
@@ -0,0 +1,78 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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 org.apache.james.imap.store.streaming;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * {@link RewindableInputStream} implementations which stores the data into a {@link File}. This is
+ * useful for big data
+ *
+ */
+public class FileRewindableInputStream extends AbstractRewindableInputStream{
+
+ private File f;
+ private FileOutputStream fOut;
+ private FileInputStream fIn;
+
+ public FileRewindableInputStream(InputStream in) throws IOException {
+ super(in);
+ }
+
+ @Override
+ protected OutputStream getRewindOutputStream() throws IOException {
+ if (f == null) {
+ f = File.createTempFile("rewindable", ".tmp");
+ }
+ if (fOut == null) {
+ fOut = new FileOutputStream(f);
+
+ }
+ return fOut;
+ }
+
+ @Override
+ protected void afterRewindComplete() throws IOException {
+ fIn = new FileInputStream(f);
+ }
+
+ @Override
+ protected void dispose() throws IOException {
+ if (f != null) {
+ f.delete();
+ }
+ }
+
+ @Override
+ protected InputStream getRewindInputStream() throws IOException {
+ if (f == null) {
+ f = File.createTempFile("rewindable", ".tmp");
+ }
+ if (fIn == null) {
+
+ fIn = new FileInputStream(f);
+ }
+ return fIn;
+ }
+}
Added: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/FullByteContent.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/FullByteContent.java?rev=951398&view=auto
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/FullByteContent.java (added)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/FullByteContent.java Fri Jun 4 13:07:05 2010
@@ -0,0 +1,65 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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 org.apache.james.imap.store.streaming;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+import java.util.List;
+
+import org.apache.james.imap.mailbox.MessageResult;
+
+/**
+ * Content which holds the full content, including {@link Header} objets
+ *
+ */
+public final class FullByteContent extends AbstractFullContent {
+ private final ByteBuffer contents;
+ private final long size;
+
+ public FullByteContent(final ByteBuffer contents, final List<MessageResult.Header> headers) throws IOException {
+ super(headers);
+ this.contents = contents;
+ this.size = caculateSize();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.mailbox.Content#size()
+ */
+ public long size() {
+ return size;
+ }
+
+ @Override
+ protected void bodyWriteTo(WritableByteChannel channel) throws IOException {
+ contents.rewind();
+ writeAll(channel, contents);
+ }
+
+ @Override
+ protected long getBodySize() throws IOException {
+ return contents.limit();
+ }
+
+}
Added: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/InMemoryRewindableInputStream.java
URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/InMemoryRewindableInputStream.java?rev=951398&view=auto
==============================================================================
--- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/InMemoryRewindableInputStream.java (added)
+++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/streaming/InMemoryRewindableInputStream.java Fri Jun 4 13:07:05 2010
@@ -0,0 +1,62 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you 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 org.apache.james.imap.store.streaming;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * {@link RewindableInputStream} implementations which stores the data into a {@link ByteArrayOutputStream}. This is
+ * only useful for small data, because it is complete handled in memory
+ *
+ */
+public class InMemoryRewindableInputStream extends AbstractRewindableInputStream{
+
+ private ByteArrayOutputStream out;
+ private ByteArrayInputStream in;
+ public InMemoryRewindableInputStream(InputStream wrappedIn) throws IOException {
+ super(wrappedIn);
+ this.out = new ByteArrayOutputStream();
+ this.in = new ByteArrayInputStream(out.toByteArray());
+ }
+
+ @Override
+ protected void afterRewindComplete() throws IOException {
+ in = new ByteArrayInputStream(out.toByteArray());
+ }
+
+ @Override
+ protected void dispose() throws IOException {
+ // nothing todo
+ }
+
+ @Override
+ protected InputStream getRewindInputStream() {
+ return in;
+ }
+
+ @Override
+ protected OutputStream getRewindOutputStream() {
+ return out;
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org