darrell 2002/12/03 22:06:45 Modified: proposals/imap2/java/org/apache/james/imapserver JamesImapHost.java proposals/imap2/java/org/apache/james/imapserver/commands CommandParser.java proposals/imap2/test/org/apache/james/imapserver CommandParserTest.java Copy.test ImapHostTest.java Log: IMAP Proposal updates. * Fixed JamesImapHost.copyMessage() implementation. * Handle '*' and ',' in "set" parameters, eg 1:* and 1,3,4 Revision Changes Path 1.5 +19 -7 jakarta-james/proposals/imap2/java/org/apache/james/imapserver/JamesImapHost.java Index: JamesImapHost.java =================================================================== RCS file: /home/cvs/jakarta-james/proposals/imap2/java/org/apache/james/imapserver/JamesImapHost.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- JamesImapHost.java 3 Dec 2002 14:00:11 -0000 1.4 +++ JamesImapHost.java 4 Dec 2002 06:06:44 -0000 1.5 @@ -13,19 +13,20 @@ import org.apache.james.imapserver.store.ImapMailbox; import org.apache.james.imapserver.store.MailboxException; import org.apache.james.imapserver.store.SimpleImapMessage; +import org.apache.james.imapserver.store.MessageFlags; import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.framework.logger.ConsoleLogger; -import examples.messages; - import javax.mail.search.SearchTerm; import javax.mail.internet.MimeMessage; +import javax.mail.MessagingException; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.StringTokenizer; import java.util.Map; import java.util.HashMap; +import java.util.Date; /** * An initial implementation of an ImapHost. By default, uses, @@ -313,13 +314,24 @@ return matchedUids; } + /** @see {@link ImapHost#copyMessage } */ public void copyMessage( long uid, ImapMailbox currentMailbox, ImapMailbox toMailbox ) throws MailboxException { - SimpleImapMessage message = currentMailbox.getMessage( uid ); - toMailbox.createMessage( message.getMimeMessage(), - message.getFlags(), - message.getInternalDate() ); + SimpleImapMessage originalMessage = currentMailbox.getMessage( uid ); + MimeMessage newMime = null; + try { + newMime = new MimeMessage( originalMessage.getMimeMessage() ); + } + catch ( MessagingException e ) { + // TODO chain. + throw new MailboxException( "Messaging exception: " + e.getMessage() ); + } + MessageFlags newFlags = new MessageFlags(); + newFlags.setAll( originalMessage.getFlags() ); + Date newDate = originalMessage.getInternalDate(); + + toMailbox.createMessage( newMime, newFlags, newDate); } /** 1.5 +60 -8 jakarta-james/proposals/imap2/java/org/apache/james/imapserver/commands/CommandParser.java Index: CommandParser.java =================================================================== RCS file: /home/cvs/jakarta-james/proposals/imap2/java/org/apache/james/imapserver/commands/CommandParser.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- CommandParser.java 3 Dec 2002 14:00:11 -0000 1.4 +++ CommandParser.java 4 Dec 2002 06:06:44 -0000 1.5 @@ -15,6 +15,8 @@ import java.util.Date; import java.util.TimeZone; +import java.util.List; +import java.util.ArrayList; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.text.ParseException; @@ -404,15 +406,37 @@ CharacterValidator validator = new MessageSetCharValidator(); String nextWord = consumeWord( request, validator ); - int pos = nextWord.indexOf( ':' ); + int commaPos = nextWord.indexOf( ',' ); + if ( commaPos == -1 ) { + return singleRangeSet( nextWord ); + } + + CompoundIdSet compoundSet = new CompoundIdSet(); + int pos = 0; + while ( commaPos != -1 ) { + String range = nextWord.substring( pos, commaPos ); + IdSet set = singleRangeSet( range ); + compoundSet.addIdSet( set ); + + pos = commaPos + 1; + commaPos = nextWord.indexOf( ',', pos ); + } + String range = nextWord.substring( pos ); + compoundSet.addIdSet( singleRangeSet( range ) ); + return compoundSet; + } + + private IdSet singleRangeSet( String range ) throws ProtocolException + { + int pos = range.indexOf( ':' ); try { if ( pos == -1 ) { - long value = Long.parseLong( nextWord ); + long value = parseLong( range ); return new HighLowIdSet( value, value ); } else { - long lowVal = Long.parseLong( nextWord.substring(0, pos ) ); - long highVal = Long.parseLong( nextWord.substring( pos + 1 ) ); + long lowVal = parseLong( range.substring(0, pos ) ); + long highVal = parseLong( range.substring( pos + 1 ) ); return new HighLowIdSet( lowVal, highVal ); } } @@ -421,6 +445,12 @@ } } + private long parseLong( String value ) { + if ( value.length() == 1 && value.charAt(0) == '*' ) { + return Long.MAX_VALUE; + } + return Long.parseLong( value ); + } /** * Provides the ability to ensure characters are part of a permitted set. */ @@ -464,7 +494,8 @@ { public boolean isValid( char chr ) { - return ( chr >= '0' && chr <= '9' ); + return ( ( chr >= '0' && chr <= '9' ) || + chr == '*' ); } } @@ -481,9 +512,10 @@ { public boolean isValid( char chr ) { - return isDigit( chr ) || + return ( isDigit( chr ) || chr == ':' || - chr == ','; + chr == '*' || + chr == ',' ); } private boolean isDigit( char chr ) @@ -505,6 +537,26 @@ public boolean includes( long value ) { return ( lowVal <= value ) && ( value <= highVal ); + } + } + + private class CompoundIdSet implements IdSet + { + private List idSets = new ArrayList(); + + void addIdSet( IdSet set ) { + idSets.add( set ); + } + + public boolean includes( long value ) + { + for ( int i = 0; i < idSets.size(); i++ ) { + IdSet idSet = ( IdSet ) idSets.get( i ); + if ( idSet.includes( value ) ) { + return true; + } + } + return false; } } 1.5 +41 -1 jakarta-james/proposals/imap2/test/org/apache/james/imapserver/CommandParserTest.java Index: CommandParserTest.java =================================================================== RCS file: /home/cvs/jakarta-james/proposals/imap2/test/org/apache/james/imapserver/CommandParserTest.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- CommandParserTest.java 3 Dec 2002 14:00:13 -0000 1.4 +++ CommandParserTest.java 4 Dec 2002 06:06:45 -0000 1.5 @@ -8,6 +8,7 @@ package org.apache.james.imapserver; import org.apache.james.imapserver.commands.CommandParser; +import org.apache.james.imapserver.commands.IdSet; import junit.framework.TestCase; @@ -167,6 +168,45 @@ formatter.setTimeZone( TimeZone.getTimeZone( "UTC" )); String actual = formatter.format( parser.dateTime( request ) ); assertEquals( "19710320 00:23:02", actual ); + } + + /** + * Tests parsing of "set" arguments. + */ + public void testIdSet() throws Exception + { + String testRequest = "8 25 1:4 33:* 2,3,4 1,4:6,8:* "; + ImapRequestLineReader request = getRequest( testRequest ); + + IdSet idSet; + idSet = parser.set( request ); + checkSet( idSet, new long[]{8}, new long[]{0, 2, 7, 9, 20, Long.MAX_VALUE } ); + + idSet = parser.set( request ); + checkSet( idSet, new long[]{ 25 }, new long[]{ 0, 5, 20, 30, Long.MAX_VALUE } ); + + idSet = parser.set( request ); + checkSet( idSet, new long[]{ 1, 2, 3, 4 }, new long[]{0, 5, 10 } ); + + idSet = parser.set( request ); + checkSet( idSet, new long[]{ 33, 35, 100, 1000, Long.MAX_VALUE}, new long[]{0, 1, 32}); + + idSet = parser.set( request ); + checkSet( idSet, new long[]{ 2,3,4}, new long[]{0, 1, 5,8 }); + + idSet = parser.set( request ); + checkSet( idSet, new long[]{ 1,4,5,6,8,100,1000,Long.MAX_VALUE}, new long[]{0,2,3,7}); + + } + + private void checkSet( IdSet idSet, long[] includes, long[] excludes ) + { + for ( int i = 0; i < includes.length; i++ ) { + assertTrue( idSet.includes( includes[i] )); + } + for ( int i = 0; i < excludes.length; i++ ) { + assertTrue( ! idSet.includes( excludes[i] )); + } } /** 1.2 +8 -0 jakarta-james/proposals/imap2/test/org/apache/james/imapserver/Copy.test Index: Copy.test =================================================================== RCS file: /home/cvs/jakarta-james/proposals/imap2/test/org/apache/james/imapserver/Copy.test,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- Copy.test 3 Dec 2002 14:00:13 -0000 1.1 +++ Copy.test 4 Dec 2002 06:06:45 -0000 1.2 @@ -5,16 +5,24 @@ S: \* STATUS copied \(MESSAGES 0\) S: a1 OK STATUS completed +# mark one message as deleted before copying (to check that flags are copied) C: a1 STORE 3 FLAGS (\Deleted) S: \* 3 FETCH \(FLAGS \(\\Deleted\) S: a1 OK STORE completed +# copy messages 2-4 C: a1 COPY 2:4 copied S: a1 OK COPY completed +# Check there's 3 messages in the copied mailbox C: a1 STATUS copied (MESSAGES) S: \* STATUS copied \(MESSAGES 3\) S: a1 OK STATUS completed + +# Modify an original after copying, to ensure it's not the same message. +C: a1 STORE 2 FLAGS (\Flagged) +S: \* 2 FETCH \(FLAGS \(\\Flagged\) +S: a1 OK STORE completed C: a1 SELECT copied S: \* FLAGS \(\\Answered \\Deleted \\Draft \\Flagged \\Seen\) 1.4 +3 -1 jakarta-james/proposals/imap2/test/org/apache/james/imapserver/ImapHostTest.java Index: ImapHostTest.java =================================================================== RCS file: /home/cvs/jakarta-james/proposals/imap2/test/org/apache/james/imapserver/ImapHostTest.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- ImapHostTest.java 27 Nov 2002 01:59:22 -0000 1.3 +++ ImapHostTest.java 4 Dec 2002 06:06:45 -0000 1.4 @@ -25,6 +25,8 @@ * - Rename * - Rename Inbox * - ListMailboxes + * - Copying messages - need to make sure that the copied message + * is independent of the original * * @author Darrell DeBoer <[EMAIL PROTECTED]> *
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>