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 jo...@apache.org on 2006/10/09 19:15:42 UTC
svn commit: r454432 [12/14] - in /james/server/sandbox/imap-integration: ./
lib/ src/java/ src/java/org/apache/james/imapserver/
src/java/org/apache/james/imapserver/commands/
src/java/org/apache/james/imapserver/debug/
src/java/org/apache/james/imapse...
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/util/SqlResources.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/util/SqlResources.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/util/SqlResources.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/util/SqlResources.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,371 @@
+/****************************************************************
+ * 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.mailboxmanager.util;
+
+import org.apache.oro.text.perl.MalformedPerl5PatternException;
+import org.apache.oro.text.perl.Perl5Util;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+
+/**
+ * Provides a set of SQL String resources (eg SQL Strings)
+ * to use for a database connection.
+ * This class allows SQL strings to be customised to particular
+ * database products, by detecting product information from the
+ * jdbc DatabaseMetaData object.
+ *
+ */
+public class SqlResources
+{
+ /**
+ * A map of statement types to SQL statements
+ */
+ private Map m_sql = new HashMap();
+
+ /**
+ * A map of engine specific options
+ */
+ private Map m_dbOptions = new HashMap();
+
+ /**
+ * A set of all used String values
+ */
+ static private Map stringTable = java.util.Collections.synchronizedMap(new HashMap());
+
+ /**
+ * A Perl5 regexp matching helper class
+ */
+ private Perl5Util m_perl5Util = new Perl5Util();
+
+ /**
+ * Configures a DbResources object to provide SQL statements from a file.
+ *
+ * SQL statements returned may be specific to the particular type
+ * and version of the connected database, as well as the database driver.
+ *
+ * Parameters encoded as $(parameter} in the input file are
+ * replace by values from the parameters Map, if the named parameter exists.
+ * Parameter values may also be specified in the resourceSection element.
+ *
+ * @param sqlFile the input file containing the string definitions
+ * @param sqlDefsSection
+ * the xml element containing the strings to be used
+ * @param conn the Jdbc DatabaseMetaData, taken from a database connection
+ * @param configParameters a map of parameters (name-value string pairs) which are
+ * replaced where found in the input strings
+ */
+ public void init(URL url, String sqlDefsSection,
+ Connection conn, Map configParameters)
+ throws Exception
+ {
+ // Parse the sqlFile as an XML document.
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document sqlDoc = builder.parse(url.openStream());
+
+ // First process the database matcher, to determine the
+ // sql statements to use.
+ Element dbMatcherElement =
+ (Element)(sqlDoc.getElementsByTagName("dbMatchers").item(0));
+ String dbProduct = null;
+ if ( dbMatcherElement != null ) {
+ dbProduct = matchDbConnection(conn, dbMatcherElement);
+ m_perl5Util = null; // release the PERL matcher!
+ }
+
+ // Now get the options valid for the database product used.
+ Element dbOptionsElement =
+ (Element)(sqlDoc.getElementsByTagName("dbOptions").item(0));
+ if ( dbOptionsElement != null ) {
+ // First populate the map with default values
+ populateDbOptions("", dbOptionsElement, m_dbOptions);
+ // Now update the map with specific product values
+ if ( dbProduct != null ) {
+ populateDbOptions(dbProduct, dbOptionsElement, m_dbOptions);
+ }
+ }
+
+
+ // Now get the section defining sql for the repository required.
+ NodeList sections = sqlDoc.getElementsByTagName("sqlDefs");
+ int sectionsCount = sections.getLength();
+ Element sectionElement = null;
+ boolean found = false;
+ for (int i = 0; i < sectionsCount; i++ ) {
+ sectionElement = (Element)(sections.item(i));
+ String sectionName = sectionElement.getAttribute("name");
+ if ( sectionName != null && sectionName.equals(sqlDefsSection) ) {
+ found = true;
+ break;
+ }
+
+ }
+ if ( !found ) {
+ StringBuffer exceptionBuffer =
+ new StringBuffer(64)
+ .append("Error loading sql definition file. ")
+ .append("The element named \'")
+ .append(sqlDefsSection)
+ .append("\' does not exist.");
+ throw new RuntimeException(exceptionBuffer.toString());
+ }
+
+ // Get parameters defined within the file as defaults,
+ // and use supplied parameters as overrides.
+ Map parameters = new HashMap();
+ // First read from the <params> element, if it exists.
+ Element parametersElement =
+ (Element)(sectionElement.getElementsByTagName("parameters").item(0));
+ if ( parametersElement != null ) {
+ NamedNodeMap params = parametersElement.getAttributes();
+ int paramCount = params.getLength();
+ for (int i = 0; i < paramCount; i++ ) {
+ Attr param = (Attr)params.item(i);
+ String paramName = param.getName();
+ String paramValue = param.getValue();
+ parameters.put(paramName, paramValue);
+ }
+ }
+ // Then copy in the parameters supplied with the call.
+ parameters.putAll(configParameters);
+
+ // 2 maps - one for storing default statements,
+ // the other for statements with a "db" attribute matching this
+ // connection.
+ Map defaultSqlStatements = new HashMap();
+ Map dbProductSqlStatements = new HashMap();
+
+ // Process each sql statement, replacing string parameters,
+ // and adding to the appropriate map..
+ NodeList sqlDefs = sectionElement.getElementsByTagName("sql");
+ int sqlCount = sqlDefs.getLength();
+ for ( int i = 0; i < sqlCount; i++ ) {
+ // See if this needs to be processed (is default or product specific)
+ Element sqlElement = (Element)(sqlDefs.item(i));
+ String sqlDb = sqlElement.getAttribute("db");
+ Map sqlMap;
+ if ( sqlDb.equals("")) {
+ // default
+ sqlMap = defaultSqlStatements;
+ }
+ else if (sqlDb.equals(dbProduct) ) {
+ // Specific to this product
+ sqlMap = dbProductSqlStatements;
+ }
+ else {
+ // for a different product
+ continue;
+ }
+
+ // Get the key and value for this SQL statement.
+ String sqlKey = sqlElement.getAttribute("name");
+ if ( sqlKey == null ) {
+ // ignore statements without a "name" attribute.
+ continue;
+ }
+ String sqlString = sqlElement.getFirstChild().getNodeValue();
+
+ // Do parameter replacements for this sql string.
+ Iterator paramNames = parameters.keySet().iterator();
+ StringBuffer replaceBuffer = new StringBuffer(64);
+ while ( paramNames.hasNext() ) {
+ String paramName = (String)paramNames.next();
+ String paramValue = (String)parameters.get(paramName);
+ replaceBuffer.append("${").append(paramName).append("}");
+ sqlString = substituteSubString(sqlString, replaceBuffer.toString(), paramValue);
+ if (paramNames.hasNext()) replaceBuffer.setLength(0);
+ }
+
+ // See if we already have registered a string of this value
+ String shared = (String) stringTable.get(sqlString);
+ // If not, register it -- we will use it next time
+ if (shared == null) {
+ stringTable.put(sqlString, sqlString);
+ } else {
+ sqlString = shared;
+ }
+
+ // Add to the sqlMap - either the "default" or the "product" map
+ sqlMap.put(sqlKey, sqlString);
+ }
+
+ // Copy in default strings, then overwrite product-specific ones.
+ m_sql.putAll(defaultSqlStatements);
+ m_sql.putAll(dbProductSqlStatements);
+ }
+
+ /**
+ * Compares the DatabaseProductName value for a jdbc Connection
+ * against a set of regular expressions defined in XML.
+ * The first successful match defines the name of the database product
+ * connected to. This value is then used to choose the specific SQL
+ * expressions to use.
+ *
+ * @param conn the JDBC connection being tested
+ * @param dbMatchersElement the XML element containing the database type information
+ *
+ * @return the type of database to which James is connected
+ *
+ */
+ private String matchDbConnection(Connection conn,
+ Element dbMatchersElement)
+ throws MalformedPerl5PatternException, SQLException
+ {
+ String dbProductName = conn.getMetaData().getDatabaseProductName();
+
+ NodeList dbMatchers =
+ dbMatchersElement.getElementsByTagName("dbMatcher");
+ for ( int i = 0; i < dbMatchers.getLength(); i++ ) {
+ // Get the values for this matcher element.
+ Element dbMatcher = (Element)dbMatchers.item(i);
+ String dbMatchName = dbMatcher.getAttribute("db");
+ StringBuffer dbProductPatternBuffer =
+ new StringBuffer(64)
+ .append("/")
+ .append(dbMatcher.getAttribute("databaseProductName"))
+ .append("/i");
+
+ // If the connection databaseProcuctName matches the pattern,
+ // use the match name from this matcher.
+ if ( m_perl5Util.match(dbProductPatternBuffer.toString(), dbProductName) ) {
+ return dbMatchName;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets all the name/value pair db option couples related to the dbProduct,
+ * and put them into the dbOptionsMap.
+ *
+ * @param dbProduct the db product used
+ * @param dbOptionsElement the XML element containing the options
+ * @param dbOptionsMap the <CODE>Map</CODE> to populate
+ *
+ */
+ private void populateDbOptions(String dbProduct, Element dbOptionsElement, Map dbOptionsMap)
+ {
+ NodeList dbOptions =
+ dbOptionsElement.getElementsByTagName("dbOption");
+ for ( int i = 0; i < dbOptions.getLength(); i++ ) {
+ // Get the values for this option element.
+ Element dbOption = (Element)dbOptions.item(i);
+ // Check is this element is pertinent to the dbProduct
+ // Notice that a missing attribute returns "", good for defaults
+ if (!dbProduct.equalsIgnoreCase(dbOption.getAttribute("db"))) {
+ continue;
+ }
+ // Put into the map
+ dbOptionsMap.put(dbOption.getAttribute("name"), dbOption.getAttribute("value"));
+ }
+ }
+
+ /**
+ * Replace substrings of one string with another string and return altered string.
+ * @param input input string
+ * @param find the string to replace
+ * @param replace the string to replace with
+ * @return the substituted string
+ */
+ private String substituteSubString( String input,
+ String find,
+ String replace )
+ {
+ int find_length = find.length();
+ int replace_length = replace.length();
+
+ StringBuffer output = new StringBuffer(input);
+ int index = input.indexOf(find);
+ int outputOffset = 0;
+
+ while ( index > -1 ) {
+ output.replace(index + outputOffset, index + outputOffset + find_length, replace);
+ outputOffset = outputOffset + (replace_length - find_length);
+
+ index = input.indexOf(find, index + find_length);
+ }
+
+ String result = output.toString();
+ return result;
+ }
+
+ /**
+ * Returns a named SQL string for the specified connection,
+ * replacing parameters with the values set.
+ *
+ * @param name the name of the SQL resource required.
+ * @return the requested resource
+ */
+ public String getSqlString(String name)
+ {
+ return (String)m_sql.get(name);
+ }
+
+ /**
+ * Returns a named SQL string for the specified connection,
+ * replacing parameters with the values set.
+ *
+ * @param name the name of the SQL resource required.
+ * @param required true if the resource is required
+ * @return the requested resource
+ * @throws ConfigurationException
+ * if a required resource cannot be found.
+ */
+ public String getSqlString(String name, boolean required)
+ {
+ String sql = getSqlString(name);
+
+ if (sql == null && required) {
+ StringBuffer exceptionBuffer =
+ new StringBuffer(64)
+ .append("Required SQL resource: '")
+ .append(name)
+ .append("' was not found.");
+ throw new RuntimeException(exceptionBuffer.toString());
+ }
+ return sql;
+ }
+
+ /**
+ * Returns the dbOption string value set for the specified dbOption name.
+ *
+ * @param name the name of the dbOption required.
+ * @return the requested dbOption value
+ */
+ public String getDbOption(String name)
+ {
+ return (String)m_dbOptions.get(name);
+ }
+
+}
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/FlaggedSessionMailboxWrapper.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/FlaggedSessionMailboxWrapper.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/FlaggedSessionMailboxWrapper.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/FlaggedSessionMailboxWrapper.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,43 @@
+package org.apache.james.mailboxmanager.wrapper;
+
+import javax.mail.Flags;
+
+import org.apache.james.mailboxmanager.GeneralMessageSet;
+import org.apache.james.mailboxmanager.MailboxListener;
+import org.apache.james.mailboxmanager.MailboxManagerException;
+import org.apache.james.mailboxmanager.MessageResult;
+import org.apache.james.mailboxmanager.mailbox.FlaggedMailbox;
+
+public class FlaggedSessionMailboxWrapper extends SessionMailboxWrapper {
+
+ public FlaggedSessionMailboxWrapper(FlaggedMailbox flaggedMailbox) throws MailboxManagerException {
+ super(flaggedMailbox);
+ }
+
+
+ public synchronized MessageResult[] expunge(GeneralMessageSet set, int result) throws MailboxManagerException {
+ return addMsnToResults(((FlaggedMailbox) mailbox).expunge(toUidSet(set), noMsnResult(result)),result);
+ }
+
+ public MessageResult getFirstUnseen(int result) throws MailboxManagerException {
+ return addMsnResult(((FlaggedMailbox) mailbox).getFirstUnseen(noMsnResult(result)),result);
+ }
+
+ public Flags getPermanentFlags() {
+ return ((FlaggedMailbox) mailbox).getPermanentFlags();
+ }
+
+ public int getRecentCount(boolean reset) throws MailboxManagerException {
+ return ((FlaggedMailbox) mailbox).getRecentCount(reset);
+ }
+
+ public int getUnseenCount() throws MailboxManagerException {
+ return ((FlaggedMailbox) mailbox).getUnseenCount();
+ }
+
+ public void setFlags(Flags flags, boolean value, boolean replace, GeneralMessageSet set, MailboxListener silentListener) throws MailboxManagerException {
+ ((FlaggedMailbox) mailbox).setFlags(flags, value, replace,toUidSet(set), silentListener);
+ }
+
+
+}
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/ImapMailboxSessionWrapper.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/ImapMailboxSessionWrapper.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/ImapMailboxSessionWrapper.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/ImapMailboxSessionWrapper.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,58 @@
+package org.apache.james.mailboxmanager.wrapper;
+
+import javax.mail.search.SearchTerm;
+
+import org.apache.james.mailboxmanager.GeneralMessageSet;
+import org.apache.james.mailboxmanager.MailboxListener;
+import org.apache.james.mailboxmanager.MailboxManagerException;
+import org.apache.james.mailboxmanager.MessageResult;
+import org.apache.james.mailboxmanager.Quota;
+import org.apache.james.mailboxmanager.acl.MailboxRights;
+import org.apache.james.mailboxmanager.impl.MailboxEventDispatcher;
+import org.apache.james.mailboxmanager.mailbox.ImapMailbox;
+import org.apache.james.mailboxmanager.mailbox.ImapMailboxSession;
+
+public class ImapMailboxSessionWrapper extends FlaggedSessionMailboxWrapper
+ implements ImapMailboxSession {
+
+ protected MailboxEventDispatcher eventDispatcher = new MailboxEventDispatcher();
+
+ public ImapMailboxSessionWrapper(ImapMailbox imapMailbox) throws MailboxManagerException {
+ super(imapMailbox);
+ }
+
+ public MailboxRights myRights() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Quota[] getQuota() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+
+ public boolean isSelectable() {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+ public long getUidValidity() throws MailboxManagerException {
+ return ((ImapMailbox) mailbox).getUidValidity();
+ }
+
+ public long getUidNext() throws MailboxManagerException {
+ return ((ImapMailbox) mailbox).getUidNext();
+ }
+
+ public MessageResult[] search(GeneralMessageSet set, SearchTerm searchTerm, int result) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+
+
+
+}
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/NumberStableSessionWrapper.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/NumberStableSessionWrapper.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/NumberStableSessionWrapper.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/NumberStableSessionWrapper.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,169 @@
+package org.apache.james.mailboxmanager.wrapper;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.apache.james.mailboxmanager.GeneralMessageSet;
+import org.apache.james.mailboxmanager.MailboxListener;
+import org.apache.james.mailboxmanager.MailboxManagerException;
+import org.apache.james.mailboxmanager.MessageResult;
+import org.apache.james.mailboxmanager.impl.GeneralMessageSetImpl;
+import org.apache.james.mailboxmanager.impl.MailboxEventDispatcher;
+import org.apache.james.mailboxmanager.impl.MessageResultImpl;
+import org.apache.james.mailboxmanager.mailbox.EventQueueingSessionMailbox;
+import org.apache.james.mailboxmanager.mailbox.EventTriggerMailbox;
+import org.apache.james.mailboxmanager.mailbox.GeneralMailbox;
+import org.apache.james.mailboxmanager.util.AbstractLogEnabled;
+
+public class NumberStableSessionWrapper extends AbstractLogEnabled implements EventQueueingSessionMailbox,
+ MailboxListener {
+
+ protected GeneralMailbox mailbox;
+
+ private UidToMsnBidiMap numberCache = null;
+
+ protected Map flagEventMap = new TreeMap();
+
+ protected SortedSet expungedEventList = new TreeSet();
+
+ private MailboxEventDispatcher eventDispatcher = new MailboxEventDispatcher();
+
+ public NumberStableSessionWrapper(GeneralMailbox generalMailbox) throws MailboxManagerException {
+ this.mailbox=generalMailbox;
+ ((EventTriggerMailbox)mailbox).addListener(eventDispatcher, MessageResult.UID);
+ getNumberCache();
+ eventDispatcher.addMailboxListener(this);
+ }
+
+ protected UidToMsnBidiMap getNumberCache() throws MailboxManagerException {
+ if (numberCache == null) {
+ MessageResult[] mr = mailbox.getMessages(GeneralMessageSetImpl
+ .all(), MessageResult.UID);
+ numberCache = new UidToMsnBidiMap();
+ for (int i = 0; i < mr.length; i++) {
+ numberCache.add(mr[i].getUid());
+ }
+ }
+ return numberCache;
+ }
+
+ protected GeneralMessageSet toUidSet(GeneralMessageSet set)
+ throws MailboxManagerException {
+
+ if (set.getType() == GeneralMessageSet.TYPE_MSN) {
+ set = GeneralMessageSetImpl.uidRange(getNumberCache().getUid(
+ set.getMsnFrom()), getNumberCache().getUid(set.getMsnTo()));
+ }
+ return set;
+ }
+
+ protected static int noMsnResult(int result) {
+ if ((result & MessageResult.MSN) > 0) {
+ result |= MessageResult.UID;
+ result -= MessageResult.MSN;
+ }
+ return result;
+ }
+
+ protected MessageResult[] addMsnToResults(MessageResult[] mr, int result)
+ throws MailboxManagerException {
+ MessageResult[] translated = new MessageResult[mr.length];
+ for (int i = 0; i < translated.length; i++) {
+ translated[i] = addMsnResult(mr[i], result);
+ }
+ return translated;
+ }
+
+ protected MessageResult addMsnResult(MessageResult mr, int result)
+ throws MailboxManagerException {
+ if (mr != null) {
+ if ((result & MessageResult.MSN) > 0) {
+ // TODO copy the MessageResult because it could be another class
+ int msn = getNumberCache().getMsn(mr.getUid());
+ ((MessageResultImpl) mr).setMsn(msn);
+ }
+ }
+ return mr;
+ }
+
+ public synchronized MessageResult[] getFlagEvents(boolean reset)
+ throws MailboxManagerException {
+ final MessageResult[] msnFlagEvents = buildMsnEvents(flagEventMap.values(),false);
+ if (reset) {
+ flagEventMap = new TreeMap();
+ }
+ return msnFlagEvents;
+ }
+
+ public synchronized MessageResult[] getExpungedEvents(boolean reset)
+ throws MailboxManagerException {
+ final MessageResult[] msnExpungedEvents = buildMsnEvents(expungedEventList,reset);
+ if (reset) {
+ expungedEventList = new TreeSet();
+ }
+ return msnExpungedEvents;
+ }
+
+ protected MessageResult[] buildMsnEvents(Collection collection,boolean expunge)
+ throws MailboxManagerException {
+ final MessageResult[] msnEvents = new MessageResult[collection.size()];
+ int i=0;
+ for (Iterator iter = collection.iterator(); iter.hasNext();) {
+ MessageResult origMr = (MessageResult) iter.next();
+ MessageResultImpl newMr = new MessageResultImpl(origMr);
+ newMr.setMsn(getNumberCache().getMsn(origMr.getUid()));
+ if (expunge) {
+ getNumberCache().expunge(origMr.getUid());
+ }
+ msnEvents[i++]=newMr;
+ }
+ return msnEvents;
+ }
+
+ public void added(MessageResult result) {
+ try {
+ getNumberCache().add(result.getUid());
+ } catch (MailboxManagerException e) {
+ getLog().error("This should not happen",e);
+ }
+ }
+
+ public void expunged(MessageResult mr) {
+ getLog().debug("Expunged: "+mr);
+ expungedEventList.add(mr);
+ }
+
+ public synchronized void flagsUpdated(MessageResult mr,
+ MailboxListener silentListener) {
+ if (silentListener != this
+ || flagEventMap.containsKey(new Long(mr.getUid()))) {
+ // if there has been an external update in the past we should inform
+ // about the newest value, even if in silent mode
+ flagEventMap.put(new Long(mr.getUid()), mr);
+ }
+ }
+
+ public void mailboxDeleted() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void mailboxRenamed(String origName, String newName) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void addListener(MailboxListener listener, int result) {
+ eventDispatcher.addMailboxListener(listener);
+ }
+
+ public void removeListener(MailboxListener listener) {
+ eventDispatcher.removeMailboxListener(listener);
+ }
+
+}
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/SessionMailboxWrapper.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/SessionMailboxWrapper.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/SessionMailboxWrapper.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/SessionMailboxWrapper.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,59 @@
+package org.apache.james.mailboxmanager.wrapper;
+
+import java.util.Date;
+
+import javax.mail.internet.MimeMessage;
+
+import org.apache.james.mailboxmanager.GeneralMessageSet;
+import org.apache.james.mailboxmanager.MailboxManagerException;
+import org.apache.james.mailboxmanager.MessageResult;
+import org.apache.james.mailboxmanager.mailbox.FlaggedMailbox;
+import org.apache.james.mailboxmanager.mailbox.GeneralMailbox;
+import org.apache.james.mailboxmanager.mailbox.MailboxSession;
+
+public class SessionMailboxWrapper extends NumberStableSessionWrapper implements MailboxSession {
+
+ public SessionMailboxWrapper(GeneralMailbox generalMailbox) throws MailboxManagerException {
+ super(generalMailbox);
+ }
+
+ public MessageResult appendMessage(MimeMessage message, Date internalDate,
+ int result) throws MailboxManagerException {
+ return addMsnResult(mailbox.appendMessage(message, internalDate, noMsnResult(result)),result);
+ }
+
+ public int getMessageCount() throws MailboxManagerException {
+ return mailbox.getMessageCount();
+ }
+
+ public int getMessageResultTypes() {
+ return mailbox.getMessageResultTypes() | MessageResult.MSN;
+ }
+
+ public MessageResult[] getMessages(GeneralMessageSet set, int result)
+ throws MailboxManagerException {
+ return addMsnToResults(mailbox.getMessages(toUidSet(set),
+ noMsnResult(result)), result);
+ }
+
+ public int getMessageSetTypes() {
+ return mailbox.getMessageSetTypes() | GeneralMessageSet.TYPE_MSN;
+ }
+
+ public String getName() throws MailboxManagerException {
+ return mailbox.getName();
+ }
+
+ public MessageResult updateMessage(GeneralMessageSet messageSet, MimeMessage message, int result) throws MailboxManagerException {
+ return addMsnResult(mailbox.updateMessage(toUidSet(messageSet), message, noMsnResult(result)),result);
+ }
+
+ public void close() {
+ // TODO Auto-generated method stub
+ }
+
+ public boolean isWriteable() {
+ return true;
+ }
+
+}
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/UidToMsnBidiMap.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/UidToMsnBidiMap.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/UidToMsnBidiMap.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/mailboxmanager/wrapper/UidToMsnBidiMap.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,110 @@
+package org.apache.james.mailboxmanager.wrapper;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+public class UidToMsnBidiMap {
+
+ protected SortedMap msnToUid;
+
+ protected SortedMap uidToMsn;
+
+ protected long highestUid = 0;
+
+ protected int highestMsn = 0;
+
+ public UidToMsnBidiMap() {
+ msnToUid = new TreeMap();
+ uidToMsn = new TreeMap();
+ }
+
+ public synchronized long getUid(int msn) {
+ if (msn == -1) {
+ return -1;
+ }
+ Long uid = (Long) msnToUid.get(new Integer(msn));
+ if (uid != null) {
+ return uid.longValue();
+ } else {
+ if (msn > 0) {
+ return highestUid;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ public synchronized int getMsn(long uid) {
+ Integer msn = (Integer) uidToMsn.get(new Long(uid));
+ if (msn != null) {
+ return msn.intValue();
+ } else {
+ return -1;
+ }
+
+ }
+
+ protected synchronized void add(int msn, long uid) {
+ if (uid > highestUid) {
+ highestUid = uid;
+ }
+ msnToUid.put(new Integer(msn), new Long(uid));
+ uidToMsn.put(new Long(uid), new Integer(msn));
+ }
+
+
+
+ public synchronized void expunge(long uid) {
+ int msn=getMsn(uid);
+ remove(msn,uid);
+ List renumberMsns=new ArrayList(msnToUid.tailMap(new Integer(msn+1)).keySet());
+ for (Iterator iter = renumberMsns.iterator(); iter.hasNext();) {
+ int aMsn = ((Integer) iter.next()).intValue();
+ long aUid= getUid(aMsn);
+ remove(aMsn,aUid);
+ add(aMsn-1,aUid);
+ }
+ highestMsn--;
+ assertValidity();
+ }
+
+ protected void remove(int msn,long uid) {
+ uidToMsn.remove(new Long(uid));
+ msnToUid.remove(new Integer(msn));
+ }
+
+ synchronized void assertValidity() {
+ Integer[] msns=(Integer[])msnToUid.keySet().toArray(new Integer[0]);
+ for (int i = 0; i < msns.length; i++) {
+ if (msns[i].intValue()!=(i+1)) {
+ throw new AssertionError("Msn at position "+(i+1)+" was "+msns[i].intValue());
+ }
+ }
+ if (msns[msns.length-1].intValue()!=highestMsn) {
+ throw new AssertionError("highestMsn "+highestMsn+" msns[msns.length-1] "+msns[msns.length-1]);
+ }
+ if (!msnToUid.keySet().equals(new TreeSet(uidToMsn.values()))) {
+ System.out.println(msnToUid.keySet());
+ System.out.println(uidToMsn.values());
+ throw new AssertionError("msnToUid.keySet() does not equal uidToMsn.values()");
+ }
+ if (!uidToMsn.keySet().equals(new TreeSet(msnToUid.values()))) {
+ System.out.println(uidToMsn.keySet());
+ System.out.println(msnToUid.values());
+ throw new AssertionError("uidToMsn.keySet() does not equal msnToUid.values()");
+ }
+
+ }
+
+ public synchronized void add(long uid) {
+ if (!uidToMsn.containsKey(new Long(uid))) {
+ highestMsn++;
+ add(highestMsn, uid);
+ }
+ }
+
+}
Added: james/server/sandbox/imap-integration/src/java/org/apache/james/util/Assert.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/java/org/apache/james/util/Assert.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/java/org/apache/james/util/Assert.java (added)
+++ james/server/sandbox/imap-integration/src/java/org/apache/james/util/Assert.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,59 @@
+/***********************************************************************
+ * Copyright (c) 2000-2004 The Apache Software Foundation. *
+ * All rights reserved. *
+ * ------------------------------------------------------------------- *
+ * 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 org.apache.james.util;
+
+
+/**
+ * A set of debugging utilities.
+ */
+public final class Assert
+{
+ public static final boolean ON = true;
+
+ // Can't instantiate.
+ private Assert()
+ {
+ };
+
+ /**
+ * Checks the supplied boolean expression, throwing an AssertionException if false;
+ */
+ public static void isTrue( boolean expression )
+ {
+ if ( !expression ) {
+ throw new RuntimeException( "Assertion Failed." );
+ }
+ }
+
+ /**
+ * Fails with an assertion exception.
+ */
+ public static void fail()
+ {
+ throw new RuntimeException( "Assertion error - should not reach here." );
+ }
+
+ /**
+ * Fails, indicating not-yet-implemented features.
+ */
+ public static void notImplemented()
+ {
+ throw new RuntimeException( "Not implemented" );
+ }
+
+}
Added: james/server/sandbox/imap-integration/src/schema/project-schema.xml
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/schema/project-schema.xml?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/schema/project-schema.xml (added)
+++ james/server/sandbox/imap-integration/src/schema/project-schema.xml Mon Oct 9 10:15:30 2006
@@ -0,0 +1,85 @@
+<!DOCTYPE database SYSTEM
+ "http://db.apache.org/torque/dtd/database_3_2.dtd">
+
+<database
+ name="mailboxmanager">
+
+ <table name="mailbox" javaName="MailboxRow" description="Mailbox Table" idMethod="native">
+ <column name="mailbox_id" required="true" primaryKey="true" type="BIGINT" autoIncrement="true"
+ description="Mailbox Id"/>
+ <column name="name" required="true" type="VARCHAR" size="255"
+ description="full-namespace-name"/>
+ <column name="uid_validity" required="true" type="BIGINT"
+ description="the last used uid (default 0)"/>
+ <column name="last_uid" required="true" type="BIGINT"
+ description="the last used uid (default 0)"/>
+ <column name="message_count" type="INTEGER" default="0"
+ description="total message number"/>
+ <column name="size" type="BIGINT" default="0"
+ description="size of this mailbox in byte"/>
+ <unique>
+ <unique-column name="name" />
+ </unique>
+ </table>
+ <table name="message" javaName="MessageRow" idMethod="none" description="">
+ <column name="mailbox_id" required="true" primaryKey="true" type="BIGINT"
+ description="Mailbox Id"/>
+ <column name="uid" required="true" primaryKey="true" type="BIGINT"
+ description="the last used uid (default 0)"/>
+ <column name="internal_date" type="DATE" description="internal date" />
+ <column name="size" type="INTEGER" description="message size" />
+ <foreign-key foreignTable="mailbox" onDelete="cascade">
+ <reference local="mailbox_id" foreign="mailbox_id"/>
+ </foreign-key>
+ </table>
+ <table name="message_flags" idMethod="none">
+ <column name="mailbox_id" required="true" primaryKey="true" type="BIGINT"
+ description="Mailbox Id"/>
+ <column name="uid" required="true" primaryKey="true" type="BIGINT"
+ description=""/>
+ <column name="answered" required="true" default="0" type="BOOLEANINT"
+ description=""/>
+ <column name="deleted" required="true" default="0" type="BOOLEANINT"
+ description=""/>
+ <column name="draft" required="true" default="0" type="BOOLEANINT"
+ description=""/>
+ <column name="flagged" required="true" default="0" type="BOOLEANINT"
+ description=""/>
+ <column name="recent" required="true" default="0" type="BOOLEANINT"
+ description=""/>
+ <column name="seen" required="true" default="0" type="BOOLEANINT"
+ description=""/>
+ <foreign-key foreignTable="message" onDelete="cascade">
+ <reference local="mailbox_id" foreign="mailbox_id"/>
+ <reference local="uid" foreign="uid"/>
+ </foreign-key>
+ </table>
+ <table name="message_header" idMethod="none">
+ <column name="mailbox_id" required="true" primaryKey="true" type="BIGINT"
+ description="Mailbox Id"/>
+ <column name="uid" required="true" primaryKey="true" type="BIGINT"
+ description=""/>
+ <column name="line_number" required="true" primaryKey="true" type="INTEGER"
+ description=""/>
+ <column name="field" required="true" type="VARCHAR" size="256"
+ description="field"/>
+ <column name="value" required="true" type="VARCHAR" size="1024"
+ description="value"/>
+ <foreign-key foreignTable="message" onDelete="cascade">
+ <reference local="mailbox_id" foreign="mailbox_id"/>
+ <reference local="uid" foreign="uid"/>
+ </foreign-key>
+ </table>
+ <table name="message_body" idMethod="none">
+ <column name="mailbox_id" required="true" primaryKey="true" type="BIGINT"
+ description="Mailbox Id"/>
+ <column name="uid" required="true" primaryKey="true" type="BIGINT"
+ description=""/>
+ <column name="body" required="true" type="BLOB"
+ description="value"/>
+ <foreign-key foreignTable="message" onDelete="cascade">
+ <reference local="mailbox_id" foreign="mailbox_id"/>
+ <reference local="uid" foreign="uid"/>
+ </foreign-key>
+ </table>
+</database>
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/TestConstants.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/TestConstants.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/TestConstants.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/TestConstants.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,16 @@
+package org.apache.james.imapserver;
+
+public interface TestConstants
+{
+ final static String USER_NAME="tuser";
+ final static String USER_MAILBOX_ROOT=ImapConstants.USER_NAMESPACE+"."+USER_NAME;
+ final static String USER_PASSWORD="abc";
+ final static String USER_REALNAME="Test User";
+
+ final static String HOST_NAME="localhost";
+ final static String HOST_ADDRESS="127.0.0.1";
+ final static int HOST_PORT=10143;
+
+
+
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/AbstractCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/AbstractCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/AbstractCommand.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/AbstractCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,27 @@
+package org.apache.james.imapserver.client;
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.mail.MessagingException;
+
+public abstract class AbstractCommand implements Command {
+
+ protected List responseList = new LinkedList();
+ protected String statusResponse = null;
+ protected String command = null;
+
+ public List getExpectedResponseList() throws MessagingException, IOException {
+ return responseList ;
+ }
+
+ public String getExpectedStatusResponse() {
+ return statusResponse;
+ }
+
+ public String getCommand() {
+ return command;
+ }
+
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/Command.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/Command.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/Command.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/Command.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,24 @@
+package org.apache.james.imapserver.client;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.mail.MessagingException;
+
+public interface Command {
+
+ public List getExpectedResponseList() throws MessagingException, IOException;
+
+ /**
+ * Untagged, without leading space or trailing newline.<br>
+ * e.g. : "OK LOGIN completed."
+ */
+ public String getExpectedStatusResponse();
+
+ /**
+ * Untagged, without leading space with trailing newline. <br>
+ * e.g. : "LOGIN user password\n"
+ */
+ public String getCommand();
+
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/CopyClientCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/CopyClientCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/CopyClientCommand.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/CopyClientCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,14 @@
+package org.apache.james.imapserver.client;
+
+public class CopyClientCommand extends AbstractCommand {
+
+ public CopyClientCommand(MessageSet set,String destination) {
+ command = "";
+ if (set.isUid()) {
+ command ="UID ";
+ }
+ command += "COPY "+set + " \""+destination+"\"";
+ statusResponse="OK COPY completed.";
+ }
+
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/CreateClientCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/CreateClientCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/CreateClientCommand.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/CreateClientCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,9 @@
+package org.apache.james.imapserver.client;
+
+public class CreateClientCommand extends AbstractCommand {
+
+ public CreateClientCommand(String folder) {
+ command = "CREATE \""+folder+"\"";
+ statusResponse="OK CREATE completed.";
+ }
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/DeleteClientCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/DeleteClientCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/DeleteClientCommand.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/DeleteClientCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,9 @@
+package org.apache.james.imapserver.client;
+
+public class DeleteClientCommand extends AbstractCommand {
+
+ public DeleteClientCommand(String folder) {
+ command = "DELETE \""+folder+"\"";
+ statusResponse="OK DELETE completed.";
+ }
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/FetchCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/FetchCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/FetchCommand.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/FetchCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,225 @@
+package org.apache.james.imapserver.client;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.mail.Flags;
+import javax.mail.MessagingException;
+import javax.mail.Flags.Flag;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.james.imapserver.client.fetch.FetchBody;
+
+public class FetchCommand extends AbstractCommand {
+
+ final long from;
+
+ final long to;
+
+ boolean uid;
+
+ private MimeMessage[] msgs;
+
+ private long[] uids;
+
+ private boolean fetchFlags;
+
+ private boolean fetchRfc822Size;
+
+ private FetchBody body;
+
+ public FetchCommand(MimeMessage[] msgs, long from, long to) {
+ statusResponse = "OK FETCH completed.";
+ this.msgs = msgs;
+ this.from = from;
+ this.to = to;
+ }
+
+ public void setUids(long[] uids) {
+ this.uids=uids;
+ this.uid=true;
+ }
+
+ public String getCommand() {
+ String command = "";
+ if (uid) {
+ command += "UID ";
+ }
+ command += "fetch " + from + ":";
+ if (to > 0) {
+ command += to;
+ } else {
+ command += "*";
+ }
+ command += " (";
+ String items="";
+ // FLAGS
+ if (fetchFlags) {
+ items += " FLAGS";
+ }
+ // RFC822.SIZE
+ if (fetchRfc822Size) {
+ items += " RFC822.SIZE";
+ }
+ // BODY
+ if (body!=null) {
+ items += " "+body.getCommand();
+ }
+
+
+ if (items.length()>0) {
+ items=items.substring(1);
+ }
+
+ command += items+")\n";
+ return command;
+ }
+
+ private List getSelectedMessageNumbers() {
+ List selectedNumbers = new ArrayList();
+
+
+ if (uid) {
+ final long to;
+ if (this.to>0) {
+ to=this.to;
+ } else {
+ to=Long.MAX_VALUE;
+ }
+ for (int i=0; i< msgs.length; i++) {
+ if (uids[i]>=from && uids[i]<=to) {
+ selectedNumbers.add(new Integer((int)i+1));
+ }
+ }
+
+ } else {
+ final long from;
+ if (this.from > 0) {
+ from = this.from;
+ } else {
+ from = 1;
+ }
+
+ final long to;
+ if (this.to > 0) {
+ if (this.to > msgs.length) {
+ to = msgs.length;
+ } else {
+ to = this.to;
+ }
+ } else {
+ to = msgs.length;
+ }
+
+ for (long i = from; i <= to; i++) {
+ selectedNumbers.add(new Integer((int)i));
+ }
+ }
+
+ return selectedNumbers;
+ }
+ public String getResultForMessageNumber(int no) throws MessagingException, IOException {
+ final MimeMessage mm = msgs[no-1];
+ String result = "";
+
+ // FLAGS
+ if (fetchFlags) {
+ result +=" FLAGS ("+flagsToString(mm.getFlags())+")";
+ }
+
+ // UID
+ if (uid) {
+ final long uid=uids[no-1];
+ result += " UID "+uid;
+ }
+
+ // RFC822.SIZE
+ if (fetchRfc822Size) {
+ final int size=mm.getSize();
+ result += " RFC822.SIZE "+size;
+ }
+
+ // BODY
+ if (body!=null) {
+ result += " "+body.getResult(mm);
+ }
+
+ if (result.length()>0) {
+ // without leading space
+ result=result.substring(1);
+ }
+ return result;
+ }
+
+ public List getExpectedResponseList() throws MessagingException, IOException {
+ List responseList = new LinkedList();
+
+ List selectedNumbers = getSelectedMessageNumbers();
+
+ for (Iterator it = selectedNumbers.iterator(); it.hasNext();) {
+ final int no=((Integer)it.next()).intValue();
+ String line = "* " + no + " FETCH (";
+ line += getResultForMessageNumber(no);
+ line += ")";
+ responseList.add(line);
+ }
+ return responseList;
+
+ }
+
+ public static String flagToString(Flag flag) {
+ if (flag.equals(Flag.ANSWERED)) {
+ return "\\Answered";
+ }
+ if (flag.equals(Flag.DELETED)) {
+ return "\\Deleted";
+ }
+ if (flag.equals(Flag.DRAFT)) {
+ return "\\Draft";
+ }
+ if (flag.equals(Flag.FLAGGED)) {
+ return "\\Flagged";
+ }
+ if (flag.equals(Flag.RECENT)) {
+ return "\\Recent";
+ }
+ if (flag.equals(Flag.SEEN)) {
+ return "\\Seen";
+ }
+ throw new IllegalArgumentException("unknown Flag: "+flag);
+
+ }
+
+ public static String flagsToString(Flags flags) {
+ String result="";
+ Flag[] f=flags.getSystemFlags();
+ for (int i = 0; i < f.length; i++) {
+ result +=" "+flagToString(f[i]);
+ }
+ if (result.length()>0) {
+ // without leading space
+ result=result.substring(1);
+ }
+ return result;
+ }
+
+ public void setFetchFlags(boolean fetchFlags) {
+ this.fetchFlags=fetchFlags;
+
+ }
+
+ public void setFetchRfc822Size(boolean fetchRfc822Size) {
+ this.fetchRfc822Size=fetchRfc822Size;
+
+ }
+
+
+ public void setFetchBody(FetchBody body) {
+ this.body=body;
+
+ }
+
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/LoginCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/LoginCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/LoginCommand.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/LoginCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,14 @@
+package org.apache.james.imapserver.client;
+
+
+public class LoginCommand extends AbstractCommand {
+
+
+ public LoginCommand(String userName, String password) {
+ command="LOGIN "+userName+" "+password+"\n";
+ statusResponse="OK LOGIN completed.";
+ }
+
+
+
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/LogoutClientCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/LogoutClientCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/LogoutClientCommand.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/LogoutClientCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,11 @@
+package org.apache.james.imapserver.client;
+
+public class LogoutClientCommand extends AbstractCommand {
+
+ public LogoutClientCommand() {
+ command="LOGOUT\n";
+ statusResponse="OK LOGOUT completed.";
+ responseList.add("* BYE IMAP4rev1 Server logging out");
+ }
+
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/MessageSet.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/MessageSet.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/MessageSet.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/MessageSet.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,134 @@
+package org.apache.james.imapserver.client;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.mail.internet.MimeMessage;
+
+public class MessageSet {
+
+ private final long from;
+ private final long to;
+ private boolean useUid=false;
+ private long[] uids;
+ private MimeMessage[] msgs;
+ private ArrayList selectedMessageNumbers;
+
+ public MessageSet(MimeMessage[] msgs,long[] uids,long from,long to) {
+ this(msgs,from,to);
+ this.uids=uids;
+ this.useUid=true;
+ }
+ public MessageSet(MimeMessage[] msgs,long[] uids,long number) {
+ this(msgs,number);
+ this.uids=uids;
+ this.useUid=true;
+ }
+
+ public MessageSet(MimeMessage[] msgs,long from,long to) {
+ this(from,to);
+ this.msgs=msgs;
+ }
+ public MessageSet(MimeMessage[] msgs,long number) {
+ this(number);
+ this.msgs=msgs;
+ }
+ public MessageSet(long from,long to) {
+ this.from=from;
+ this.to=to;
+ }
+ public MessageSet(long number) {
+ this.from=-1;
+ this.to=number;
+ }
+
+ public MessageSet(MimeMessage[] msgs, long from, long to, int[] numbers, long[] uids, boolean useUid) {
+ if (useUid) {
+ from=uids[(int)from-1];
+ to=uids[(int)to-1];
+ }
+ this.msgs=msgs;
+ this.from=from;
+ this.to=to;
+ this.uids=uids;
+ this.useUid=useUid;
+ selectedMessageNumbers=new ArrayList(numbers.length);
+ for (int i = 0; i < numbers.length; i++) {
+ selectedMessageNumbers.add(new Integer(numbers[i]));
+ }
+
+ }
+ public String toString() {
+ String result="";
+ if (from>0) {
+ result += from +":";
+ }
+ if (to>0) {
+ result += to;
+ } else {
+ result += "*";
+ }
+ return result;
+ }
+
+ public boolean isUid() {
+ return useUid;
+ }
+
+ public List getSelectedMessageNumbers() {
+ if (selectedMessageNumbers==null) {
+ selectedMessageNumbers=new ArrayList();
+ if (isUid()) {
+ final long from;
+ if (this.from>0) {
+ from=this.from;
+ } else {
+ from=this.to;
+ }
+ final long to;
+ if (this.to>0) {
+ to=this.to;
+ } else {
+ to=Long.MAX_VALUE;
+ }
+ for (int i=0; i< msgs.length; i++) {
+ if (uids[i]>=from && uids[i]<=to) {
+ selectedMessageNumbers.add(new Integer((int)i+1));
+ }
+ }
+
+ } else {
+ final long from;
+ if (this.from > 0) {
+ from = this.from;
+ } else {
+ from = this.to;
+ }
+
+ final long to;
+ if (this.to > 0) {
+ if (this.to > msgs.length) {
+ to = msgs.length;
+ } else {
+ to = this.to;
+ }
+ } else {
+ to = msgs.length;
+ }
+
+ for (long i = from; i <= to; i++) {
+ selectedMessageNumbers.add(new Integer((int)i));
+ }
+ }
+ }
+ return selectedMessageNumbers;
+ }
+ public MimeMessage getMessage(int no) {
+ return msgs[no-1];
+ }
+ public long getUid(int no) {
+ return uids[no-1];
+ }
+
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/RenameClientCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/RenameClientCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/RenameClientCommand.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/RenameClientCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,9 @@
+package org.apache.james.imapserver.client;
+
+public class RenameClientCommand extends AbstractCommand {
+
+ public RenameClientCommand(String folder,String destination) {
+ command = "RENAME \""+folder+"\" \""+destination+"\"";
+ statusResponse="OK RENAME completed.";
+ }
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/SelectCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/SelectCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/SelectCommand.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/SelectCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,31 @@
+package org.apache.james.imapserver.client;
+
+import java.util.ArrayList;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.james.imapserver.util.UnsolicitedResponseGenerator;
+
+public class SelectCommand extends AbstractCommand {
+
+ int recentCount =0;
+
+ public SelectCommand(String folder,MimeMessage[] msgs,long uidv) throws MessagingException {
+
+ command="SELECT \""+folder+"\"";
+
+ UnsolicitedResponseGenerator rg=new UnsolicitedResponseGenerator();
+ rg.addByMessages(msgs);
+ recentCount = rg.getRecent();
+ rg.addUidValidity(uidv);
+ responseList=new ArrayList(rg.getResponseSet());
+ statusResponse="OK [READ-WRITE] SELECT completed.";
+
+ }
+
+ public int getRecentCount() {
+ return recentCount;
+ }
+
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/StoreClientCommand.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/StoreClientCommand.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/StoreClientCommand.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/StoreClientCommand.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,80 @@
+package org.apache.james.imapserver.client;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.mail.Flags;
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+public class StoreClientCommand extends AbstractCommand {
+
+ public static final int MODE_SET = 0;
+
+ public static final int MODE_ADD = 1;
+
+ public static final int MODE_REMOVE = 2;
+
+ private final int mode;
+
+ private final boolean silent;
+
+ private final Flags flags;
+
+ private MessageSet set;
+
+ public StoreClientCommand(int mode, boolean silent, Flags flags,
+ MessageSet set) {
+ this.mode = mode;
+ this.silent = silent;
+ this.flags = flags;
+ this.set = set;
+ this.statusResponse = "OK STORE completed.";
+ }
+
+ public String getCommand() {
+ command = "";
+ if (set.isUid()) {
+ command = "UID ";
+ }
+ command += "STORE ";
+ command += set + " ";
+
+ if (mode == MODE_ADD) {
+ command += "+";
+ } else if (mode == MODE_REMOVE) {
+ command += "-";
+ }
+ command += "FLAGS";
+ if (silent) {
+ command += ".SILENT";
+ }
+ command += " (";
+ command += FetchCommand.flagsToString(flags);
+ command += ")";
+
+ return command;
+
+ }
+
+ public List getExpectedResponseList() throws MessagingException {
+ List responseList = new LinkedList();
+ if (!silent) {
+ List selectedNumbers = set.getSelectedMessageNumbers();
+ for (Iterator it = selectedNumbers.iterator(); it.hasNext();) {
+ final int no = ((Integer) it.next()).intValue();
+ final MimeMessage mm = set.getMessage(no);
+ String line = "* " + no + " FETCH (";
+ line += "FLAGS (" + FetchCommand.flagsToString(mm.getFlags())
+ + ")";
+ if (set.isUid()) {
+ line += " UID " + set.getUid(no);
+ }
+ line += ")";
+ responseList.add(line);
+ }
+ }
+ return responseList;
+ }
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/fetch/FetchBody.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/fetch/FetchBody.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/fetch/FetchBody.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/fetch/FetchBody.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,61 @@
+package org.apache.james.imapserver.client.fetch;
+
+import java.io.IOException;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.james.imapserver.util.MessageGenerator;
+
+public class FetchBody {
+
+ final boolean peek;
+
+ private FetchHeader fetchHeader;
+
+ public FetchBody(boolean peek) {
+ this.peek = peek;
+ }
+
+ public String getCommand() {
+ String result= "";
+ if (peek) {
+ result += "BODY.PEEK[";
+ } else {
+ result += "BODY[";
+ }
+ if (fetchHeader!=null) {
+ result += fetchHeader.getCommand();
+ }
+ result += "]";
+ return result;
+ }
+
+ public String getResult(MimeMessage m) throws IOException,
+ MessagingException {
+ // TODO decide whether it should be BODY.PEEK when peek!
+ String result = "BODY[";
+ final String data;
+ if (fetchHeader != null) {
+ result += fetchHeader.getCommand();
+ data = fetchHeader.getData(m);
+ } else {
+ data = getData(m);
+ }
+ result += "] {" + data.length() + "}\r\n" + data;
+ // TODO Shouldn't we append another CRLF?
+ return result;
+ }
+
+ private String getData(MimeMessage m) throws IOException,
+ MessagingException {
+ String data = MessageGenerator.messageContentToString(m);
+ return data;
+ }
+
+ public void setFetchHeader(FetchHeader fetchHeader) {
+ this.fetchHeader = fetchHeader;
+
+ }
+
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/fetch/FetchHeader.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/fetch/FetchHeader.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/fetch/FetchHeader.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/client/fetch/FetchHeader.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,53 @@
+package org.apache.james.imapserver.client.fetch;
+
+import java.util.Enumeration;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+public class FetchHeader {
+
+ private String[] fields;
+
+ public String getCommand() {
+ if (fields == null) {
+ return "HEADER";
+ } else {
+ return "HEADER.FIELDS ("+getFormattedFieldList()+")";
+ }
+ }
+
+ private String getFormattedFieldList() {
+ String result ="";
+ for (int i = 0; i < fields.length; i++) {
+ result +=" "+fields[i];
+
+ }
+ if (result.length()>0) {
+ result=result.substring(1);
+ }
+ return result;
+ }
+
+ public String getData(MimeMessage m) throws MessagingException {
+ String result = "";
+ final Enumeration e;
+ if (fields==null) {
+ e= m.getAllHeaderLines();
+ } else {
+ e = m.getMatchingHeaderLines(fields);
+ }
+ while (e.hasMoreElements()) {
+ String line = (String) e.nextElement();
+ result += line + "\r\n";
+ }
+ result += "\r\n"; // TODO Should this be counted for size?
+ return result;
+ }
+
+ public void setFields(String[] fields) {
+ this.fields = fields;
+
+ }
+
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/commands/AbstractCommandTest.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/commands/AbstractCommandTest.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/commands/AbstractCommandTest.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/commands/AbstractCommandTest.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,40 @@
+package org.apache.james.imapserver.handler.commands;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import org.apache.james.imapserver.ImapRequestHandler;
+import org.apache.james.imapserver.ImapSession;
+import org.apache.james.imapserver.ProtocolException;
+import org.apache.james.services.User;
+import org.apache.james.services.UsersRepository;
+import org.jmock.Mock;
+import org.jmock.MockObjectTestCase;
+
+public abstract class AbstractCommandTest extends MockObjectTestCase
+{
+
+ ImapRequestHandler handler;
+ Mock mockSession;
+ Mock mockUsersRepository;
+ Mock mockUser;
+
+ public void setUp() {
+ handler=new ImapRequestHandler();
+ mockSession = mock ( ImapSession.class);
+ mockUsersRepository = mock ( UsersRepository.class );
+ mockUser = mock (User.class );
+ }
+
+ public String handleRequest(String s) throws ProtocolException {
+ ByteArrayInputStream is=new ByteArrayInputStream(s.getBytes());
+ ByteArrayOutputStream os=new ByteArrayOutputStream();
+ System.out.println("IN :"+s);
+ handler.handleRequest(is,os,(ImapSession) mockSession.proxy());
+ String out=os.toString();
+ System.out.println("OUT:"+out);
+ return out;
+ }
+
+
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/commands/LoginTest.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/commands/LoginTest.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/commands/LoginTest.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/commands/LoginTest.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,53 @@
+package org.apache.james.imapserver.handler.commands;
+
+import org.apache.james.imapserver.ImapSessionState;
+import org.apache.james.imapserver.ProtocolException;
+
+
+
+public class LoginTest extends AbstractCommandTest
+{
+
+ public void testValidUserStateNonAuth() throws ProtocolException {
+ mockSession.expects(atLeastOnce()).method("getState").will(returnValue(ImapSessionState.NON_AUTHENTICATED));
+ mockSession.expects(atLeastOnce()).method("getUsers").will(returnValue(mockUsersRepository.proxy()));
+
+ mockUsersRepository.expects(once()).method("test").with( eq("joachim2"),eq("abc")).will(returnValue(true));
+ mockUsersRepository.expects(once()).method("getUserByName").with( eq("joachim2")).will(returnValue(mockUser.proxy()));
+
+ mockSession.expects(once()).method("setAuthenticated").with( same(mockUser.proxy()));
+
+ String response = handleRequest("1 LOGIN joachim2 abc\n");
+
+ assertEquals("1 OK LOGIN completed.\r\n",response);
+ }
+ public void testInvalidUserStateNonAuth() throws ProtocolException {
+ mockSession.expects(atLeastOnce()).method("getState").will(returnValue(ImapSessionState.NON_AUTHENTICATED));
+ mockSession.expects(atLeastOnce()).method("getUsers").will(returnValue(mockUsersRepository.proxy()));
+
+ mockUsersRepository.expects(once()).method("test").with( eq("joachim2"),eq("abc")).will(returnValue(false));
+
+ String response = handleRequest("1 LOGIN joachim2 abc\n");
+
+ assertEquals("1 NO LOGIN failed. Invalid login/password\r\n",response);
+ }
+ public void testValidUserStateAuth() throws ProtocolException {
+ mockSession.expects(atLeastOnce()).method("getState").will(returnValue(ImapSessionState.AUTHENTICATED));
+
+ String response = handleRequest("1 LOGIN joachim2 abc\n");
+ assertEquals("1 NO LOGIN failed. Command not valid in this state\r\n",response);
+ }
+
+ public void testValidUserStateLogout() throws ProtocolException {
+ mockSession.expects(atLeastOnce()).method("getState").will(returnValue(ImapSessionState.LOGOUT));
+
+ String response = handleRequest("1 LOGIN joachim2 abc\n");
+ assertEquals("1 NO LOGIN failed. Command not valid in this state\r\n",response);
+ }
+ public void testValidUserStateSelected() throws ProtocolException {
+ mockSession.expects(atLeastOnce()).method("getState").will(returnValue(ImapSessionState.SELECTED));
+
+ String response = handleRequest("1 LOGIN joachim2 abc\n");
+ assertEquals("1 NO LOGIN failed. Command not valid in this state\r\n",response);
+ }
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/session/AbstractSessionTest.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/session/AbstractSessionTest.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/session/AbstractSessionTest.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/session/AbstractSessionTest.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,255 @@
+package org.apache.james.imapserver.handler.session;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import javax.mail.Flags;
+import javax.mail.MessagingException;
+import javax.mail.Flags.Flag;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.james.imapserver.ImapRequestHandler;
+import org.apache.james.imapserver.ImapSession;
+import org.apache.james.imapserver.ImapSessionImpl;
+import org.apache.james.imapserver.ProtocolException;
+import org.apache.james.imapserver.TestConstants;
+import org.apache.james.imapserver.client.Command;
+import org.apache.james.imapserver.mock.MockImapHandler;
+import org.apache.james.imapserver.mock.MockImapHandlerConfigurationData;
+import org.apache.james.imapserver.mock.MockUser;
+import org.apache.james.imapserver.store.MailboxException;
+import org.apache.james.mailboxmanager.GeneralMessageSet;
+import org.apache.james.mailboxmanager.ListResult;
+import org.apache.james.mailboxmanager.MailboxManagerException;
+import org.apache.james.mailboxmanager.MessageResult;
+import org.apache.james.mailboxmanager.impl.GeneralMessageSetImpl;
+import org.apache.james.mailboxmanager.mailbox.GeneralMailboxSession;
+import org.apache.james.mailboxmanager.mailbox.ImapMailboxSession;
+import org.apache.james.mailboxmanager.manager.GeneralManager;
+import org.jmock.MockObjectTestCase;
+
+public abstract class AbstractSessionTest extends MockObjectTestCase implements TestConstants {
+
+ GeneralManager mailboxManager;
+
+ private ImapRequestHandler handler;
+ private ImapSession session;
+
+ int counter=0;
+
+ public AbstractSessionTest() {
+ }
+
+ public void setUp() throws MailboxException, MessagingException, IOException, MailboxManagerException
+ {
+
+ MockImapHandlerConfigurationData theConfigData = new MockImapHandlerConfigurationData();
+ theConfigData.getMailboxManagerProvider().deleteEverything();
+ session = new ImapSessionImpl(theConfigData.getMailboxManagerProvider(),
+ theConfigData.getUsersRepository(), new MockImapHandler(),
+ HOST_NAME, HOST_ADDRESS);
+ handler = new ImapRequestHandler();
+ mailboxManager=theConfigData.getMailboxManagerProvider().getGeneralManagerInstance(new MockUser());
+
+ }
+
+ void createFolders(String[] folders) throws MailboxManagerException {
+ for (int i=0; i<folders.length; i++) {
+ mailboxManager.createMailbox(folders[i]);
+ }
+ }
+
+ public void appendMessagesClosed(String folder,MimeMessage[] msgs) throws MailboxManagerException, MessagingException {
+ GeneralMailboxSession mailbox=getImapMailboxSession(folder);
+ for (int i = 0; i < msgs.length; i++) {
+ msgs[i].setFlags(new Flags(Flags.Flag.RECENT), true);
+ mailbox.appendMessage(msgs[i],new Date(),MessageResult.NOTHING);
+
+ }
+ mailbox.close();
+ }
+
+ public long[] addUIDMessagesOpen(String folder,MimeMessage[] msgs) throws MailboxManagerException, MessagingException {
+ GeneralMailboxSession mailbox=getImapMailboxSession(folder);
+ long[] uids=new long[msgs.length];
+ for (int i = 0; i < msgs.length; i++) {
+ msgs[i].setFlags(new Flags(Flags.Flag.RECENT), false);
+ uids[i]=mailbox.appendMessage(msgs[i],new Date(),MessageResult.UID).getUid();
+ }
+ mailbox.close();
+ return uids;
+ }
+ public long getUidValidity(String folder) throws MailboxManagerException {
+ ImapMailboxSession mailbox=getImapMailboxSession(folder);
+ long uidv=mailbox.getUidValidity();
+ mailbox.close();
+ return uidv;
+ }
+
+ public MimeMessage[] getMessages(String folder) throws MailboxManagerException {
+ GeneralMailboxSession mailbox=getImapMailboxSession(folder);
+ MessageResult[] messageResults=mailbox.getMessages(GeneralMessageSetImpl.all(),MessageResult.MIME_MESSAGE);
+ MimeMessage[] mms=new MimeMessage[messageResults.length];
+ for (int i = 0; i < messageResults.length; i++) {
+ mms[i]=messageResults[i].getMimeMessage();
+ }
+ mailbox.close();
+ return mms;
+ }
+
+ public long[] getUids(String folder) throws MailboxManagerException {
+ GeneralMailboxSession mailbox=getImapMailboxSession(folder);
+ MessageResult[] messageResults=mailbox.getMessages(GeneralMessageSetImpl.all(),MessageResult.UID);
+
+ long[] uids=new long[messageResults.length];
+ for (int i = 0; i < messageResults.length; i++) {
+ uids[i]=messageResults[i].getUid();
+ }
+ mailbox.close();
+ return uids;
+ }
+
+ public boolean folderExists(String folder) throws MailboxManagerException {
+ return mailboxManager.existsMailbox(folder);
+ }
+
+ public String[] getFolderNames() throws MailboxManagerException {
+ ListResult[] listResults=mailboxManager.list("","*",false);
+ String[] names=new String[listResults.length];
+ for (int i = 0; i < listResults.length; i++) {
+ names[i]=listResults[i].getName();
+ }
+ return names;
+ }
+
+ public void verifyFolderList(String[] expected,String[] found) {
+ Set expectedSet=new HashSet(Arrays.asList(expected));
+ Set foundSet=new HashSet(Arrays.asList(found));
+ Set missing=new HashSet(expectedSet);
+ missing.removeAll(foundSet);
+ Set notExpected=new HashSet(foundSet);
+ notExpected.removeAll(expectedSet);
+ assertEquals("Missing folders :"+missing,0,missing.size());
+ assertEquals("Not expected folders :"+notExpected,0,notExpected.size());
+ }
+
+ public boolean isOpen(String folder) throws MessagingException {
+ // TODO implement this
+ return false;
+ }
+ public void useFolder(String folder) {
+
+ }
+ public void freeFolder(String folder) {
+
+ }
+
+ public void deleteAll(String folder) throws MailboxManagerException {
+ ImapMailboxSession mailbox=getImapMailboxSession(folder);
+ mailbox.setFlags(new Flags(Flag.DELETED),true,false,GeneralMessageSetImpl.all(),null);
+ mailbox.expunge(GeneralMessageSetImpl.all(),MessageResult.NOTHING);
+ mailbox.close();
+ }
+ public BufferedReader handleRequestReader(String s) throws ProtocolException
+ {
+ return new BufferedReader(new StringReader(handleRequest(s)));
+ }
+
+ public String handleRequest(String s) throws ProtocolException
+ {
+ ByteArrayInputStream is = new ByteArrayInputStream(s.getBytes());
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ System.out.println("IN :" + s);
+ handler.handleRequest(is, os, session);
+ String out = os.toString();
+ System.out.println("OUT:" + out);
+ return out;
+
+ }
+ protected void verify(final String command, final Set requiredResponseSet, final String requiredStatusResponse) throws ProtocolException, IOException, MessagingException {
+ Command c=new Command() {
+ public List getExpectedResponseList() throws MessagingException, IOException {
+ return new LinkedList(requiredResponseSet);
+ }
+ public String getExpectedStatusResponse() {
+ return requiredStatusResponse;
+ }
+ public String getCommand() {
+ return command;
+ }
+ };
+ verifyCommand(c);
+ }
+
+ protected void verifyCommand(Command command) throws ProtocolException, IOException, MessagingException {
+
+ BufferedReader br=handleRequestReader((++counter)+" "+command.getCommand()+"\n");
+ Set requiredResponseSet=new HashSet(command.getExpectedResponseList());
+ List rec=new ArrayList();
+ String line;
+ while ((line=br.readLine())!=null) {
+ rec.add(line);
+ }
+ assertFalse("nothing received",rec.isEmpty());
+ String statusResponse=(String)rec.get(rec.size()-1);
+ rec.remove(rec.size()-1);
+ Set responseSet=new HashSet(rec);
+ responseSet.removeAll(requiredResponseSet);
+ requiredResponseSet.removeAll(new HashSet(rec));
+ if (responseSet.size()>0) {
+ System.out.println("Not awaitet responses: "+responseSet);
+ }
+ if (requiredResponseSet.size()>0) {
+ System.out.println("Missed responses: "+requiredResponseSet);
+ }
+ assertEquals("Missed responses: "+requiredResponseSet,0,requiredResponseSet.size());
+ assertEquals("Not awaitet responses: "+responseSet,0,responseSet.size());
+ assertEquals("Status respons differs",counter+" "+command.getExpectedStatusResponse(),statusResponse);
+ }
+
+ protected void verifyCommandOrdered(Command command) throws ProtocolException, IOException, MessagingException
+ {
+ BufferedReader br=handleRequestReader((++counter)+" "+command.getCommand()+"\n");
+
+ int c=0;
+ for (Iterator it = command.getExpectedResponseList().iterator(); it.hasNext();) {
+ c++;
+ String expectedResponse = (String) it.next();
+// System.out.println("Expected: "+expectedResponse);
+ String[] expectedLines=expectedResponse.split("\r\n");
+ for (int i = 0; i < expectedLines.length; i++) {
+ String readLine=br.readLine();
+ assertNotNull("Unexpected end of response (response "+c+" line "+i+")",readLine);
+ assertEquals("Unexpected response line (response "+c+" line "+i+")",expectedLines[i],readLine);
+ }
+ }
+
+ String statusResponse=(String)br.readLine();;
+ assertEquals("Status response differs",counter+" "+command.getExpectedStatusResponse(),statusResponse);
+ String notExpected=br.readLine();
+ assertNull("did expect eof",notExpected);
+ }
+
+ public void setFlags(String mailboxName,long fromUid,long toUid,Flags flags, boolean value, boolean replace) throws MailboxManagerException {
+ ImapMailboxSession mailbox=getImapMailboxSession(mailboxName);
+ mailbox.setFlags(flags, value, replace, GeneralMessageSetImpl.uidRange(fromUid, toUid), null);
+ mailbox.close();
+ }
+ private ImapMailboxSession getImapMailboxSession(String mailboxName) throws MailboxManagerException {
+ int[] neededSets = new int[] {GeneralMessageSet.TYPE_UID};
+ int neededResults= MessageResult.UID + MessageResult.MIME_MESSAGE + MessageResult.FLAGS;
+ ImapMailboxSession mailboxSession= (ImapMailboxSession) mailboxManager.getMailboxSession(mailboxName, ImapMailboxSession.class, neededSets, neededResults);
+ return mailboxSession;
+ }
+}
Added: james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/session/BodyFetchSessionTest.java
URL: http://svn.apache.org/viewvc/james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/session/BodyFetchSessionTest.java?view=auto&rev=454432
==============================================================================
--- james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/session/BodyFetchSessionTest.java (added)
+++ james/server/sandbox/imap-integration/src/test/org/apache/james/imapserver/handler/session/BodyFetchSessionTest.java Mon Oct 9 10:15:30 2006
@@ -0,0 +1,107 @@
+package org.apache.james.imapserver.handler.session;
+
+import java.io.IOException;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.james.imapserver.ProtocolException;
+import org.apache.james.imapserver.client.FetchCommand;
+import org.apache.james.imapserver.client.LoginCommand;
+import org.apache.james.imapserver.client.SelectCommand;
+import org.apache.james.imapserver.client.fetch.FetchBody;
+import org.apache.james.imapserver.client.fetch.FetchHeader;
+import org.apache.james.imapserver.store.MailboxException;
+import org.apache.james.imapserver.util.MessageGenerator;
+import org.apache.james.mailboxmanager.MailboxManagerException;
+
+/**
+ *
+ *
+ *
+ * TODO test one message number instead of message sets (1 instead of 1:1)
+ *
+ */
+
+public class BodyFetchSessionTest extends AbstractSessionTest {
+
+ String[] onlyInbox = {USER_MAILBOX_ROOT+".INBOX"};
+ MimeMessage[] msgs= null;
+ long[] uids = null;
+
+ public void setUp() throws MailboxException, MessagingException, IOException, MailboxManagerException {
+ super.setUp();
+ msgs=MessageGenerator.generateSimplesMessages(4);
+ createFolders(onlyInbox);
+ // increase the uid
+ appendMessagesClosed(USER_MAILBOX_ROOT+".INBOX",msgs);
+ deleteAll(USER_MAILBOX_ROOT+".INBOX");
+ uids=addUIDMessagesOpen(USER_MAILBOX_ROOT+".INBOX",msgs);
+ }
+
+
+ public void testFetchCompleteAndSize() throws ProtocolException, IOException, MessagingException, MailboxManagerException {
+ verifyCommand(new LoginCommand(USER_NAME,USER_PASSWORD));
+ verifyCommand(new SelectCommand("INBOX", msgs, getUidValidity(USER_MAILBOX_ROOT+".INBOX")));
+ msgs=getMessages(USER_MAILBOX_ROOT+".INBOX");
+ FetchCommand fc=new FetchCommand(msgs,1,-1);
+ fc.setFetchRfc822Size(true);
+ fc.setFetchBody(new FetchBody(true));
+ // TODO test \Seen get's not set because of peek and vice versa
+ verifyCommandOrdered(fc);
+ }
+ public void testFetchCompleteHeader() throws ProtocolException, IOException, MessagingException, MailboxManagerException {
+ verifyCommand(new LoginCommand(USER_NAME,USER_PASSWORD));
+ verifyCommand(new SelectCommand("INBOX", msgs, getUidValidity(USER_MAILBOX_ROOT+".INBOX")));
+ msgs=getMessages(USER_MAILBOX_ROOT+".INBOX");
+ FetchCommand fc=new FetchCommand(msgs,1,-1);
+ fc.setFetchRfc822Size(true);
+ FetchBody fetchBody=new FetchBody(true);
+ fetchBody.setFetchHeader(new FetchHeader());
+ fc.setFetchBody(fetchBody);
+ verifyCommandOrdered(fc);
+ }
+ public void testFetchSomeExistingHeader() throws ProtocolException, IOException, MessagingException, MailboxManagerException {
+ verifyCommand(new LoginCommand(USER_NAME,USER_PASSWORD));
+ verifyCommand(new SelectCommand("INBOX", msgs, getUidValidity(USER_MAILBOX_ROOT+".INBOX")));
+ msgs=getMessages(USER_MAILBOX_ROOT+".INBOX");
+ FetchCommand fc=new FetchCommand(msgs,1,-1);
+ fc.setFetchRfc822Size(true);
+ FetchHeader fetchHeader=new FetchHeader();
+ fetchHeader.setFields(new String[] {"Date","From","To"});
+ FetchBody fetchBody=new FetchBody(true);
+ fetchBody.setFetchHeader(fetchHeader);
+ fc.setFetchBody(fetchBody);
+ verifyCommandOrdered(fc);
+ }
+ public void testFetchSomeNonExistingHeader() throws ProtocolException, IOException, MessagingException, MailboxManagerException {
+ verifyCommand(new LoginCommand(USER_NAME,USER_PASSWORD));
+ verifyCommand(new SelectCommand("INBOX", msgs, getUidValidity(USER_MAILBOX_ROOT+".INBOX")));
+ msgs=getMessages(USER_MAILBOX_ROOT+".INBOX");
+ FetchCommand fc=new FetchCommand(msgs,1,-1);
+ fc.setFetchRfc822Size(true);
+ FetchHeader fetchHeader=new FetchHeader();
+ fetchHeader.setFields(new String[] {"Blob","Test","Oh"});
+ FetchBody fetchBody=new FetchBody(true);
+ fetchBody.setFetchHeader(fetchHeader);
+ fc.setFetchBody(fetchBody);
+ verifyCommandOrdered(fc);
+ }
+ public void testFetchSomeNoneAndExistingHeader() throws ProtocolException, IOException, MessagingException, MailboxManagerException {
+ verifyCommand(new LoginCommand(USER_NAME,USER_PASSWORD));
+ verifyCommand(new SelectCommand("INBOX", msgs, getUidValidity(USER_MAILBOX_ROOT+".INBOX")));
+ msgs=getMessages(USER_MAILBOX_ROOT+".INBOX");
+ FetchCommand fc=new FetchCommand(msgs,1,-1);
+ fc.setFetchRfc822Size(true);
+ FetchHeader fetchHeader=new FetchHeader();
+ fetchHeader.setFields(new String[] {"To","Message-ID","Blob","Test","Oh"});
+ FetchBody fetchBody=new FetchBody(true);
+ fetchBody.setFetchHeader(fetchHeader);
+ fc.setFetchBody(fetchBody);
+ verifyCommandOrdered(fc);
+ }
+
+
+
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org