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 da...@apache.org on 2002/01/23 22:53:33 UTC

cvs commit: jakarta-james/proposals/imap/test/org/apache/james/test JamesTask.java

darrell     02/01/23 13:53:33

  Modified:    proposals/imap build-imap.xml build-test.xml
               proposals/imap/java/org/apache/james/imapserver
                        BaseCommand.java FolderRecord.java
                        ImapConstants.java
               proposals/imap/java/org/apache/james/imapserver/commands
                        AbstractAclCommand.java AuthenticateCommand.java
                        AuthenticatedSelectedStateCommand.java
                        CapabilityCommand.java CheckCommand.java
                        CloseCommand.java CommandTemplate.java
                        CopyCommand.java CreateCommand.java
                        DeleteCommand.java ExpungeCommand.java
                        ImapCommand.java ImapCommandFactory.java
                        InvalidCommand.java LoginCommand.java
                        LogoutCommand.java NamespaceCommand.java
                        NonAuthenticatedStateCommand.java NoopCommand.java
                        NotImplementedCommand.java RenameCommand.java
                        SelectedStateCommand.java StatusCommand.java
                        SubscribeCommand.java UidCommand.java
                        UnsubscribeCommand.java
               proposals/imap/test/org/apache/james/imapserver
                        Authenticate.test Capability.test IMAPTest.java
                        InitialMail.java InitialUsers.java Login.test
                        Logout.test TestAuthenticated.java
                        TestNonAuthenticated.java TestSelected.java
  Added:       proposals/imap/java/org/apache/james/imapserver/commands
                        AstringArgument.java ExamineCommand.java
                        ImapArgument.java ListArgument.java
                        ListCommand.java LsubCommand.java
                        SelectCommand.java SetArgument.java
               proposals/imap/test/org/apache/james/imapserver/commands
                        ArgumentTest.java
               proposals/imap/test/org/apache/james/test JamesTask.java
  Removed:     proposals/imap/java/org/apache/james/imapserver/commands
                        ListOrLsubCommand.java SelectOrExamineCommand.java
  Log:
  Further refactoring of Imap server proposal
  - Most ImapCommand classes now use Template Method from CommandTemplate
  - Simpler, more consistent parsing of command arguments.
  
  Revision  Changes    Path
  1.3       +5 -4      jakarta-james/proposals/imap/build-imap.xml
  
  Index: build-imap.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/build-imap.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- build-imap.xml	17 Jan 2002 06:09:00 -0000	1.2
  +++ build-imap.xml	23 Jan 2002 21:53:31 -0000	1.3
  @@ -2,7 +2,7 @@
   
   <!-- ==========================================================================
   
  - James build file $Revision: 1.2 $  Committed on $Date: 2002/01/17 06:09:00 $ by: $Author: darrell $
  + James build file $Revision: 1.3 $  Committed on $Date: 2002/01/23 21:53:31 $ by: $Author: darrell $
   
   Authors:
    Federico Barbieri <sc...@systemy.it>
  @@ -147,9 +147,9 @@
     -->
     <target name="main" depends="dist-lite" />
   
  -  <target name="build-removeDist" depends="delete-dist,dist-lite"/>
     <target name="build" depends="dist-lite" />
  -  <target name="rebuild" depends="clean,dist-lite"/>
  +  <target name="rebuild-dist" depends="delete-dist,dist-lite"/>
  +  <target name="rebuild-all" depends="clean,dist-lite"/>
   
     <!-- =================================================================== -->
     <!-- Help on usage                                                       -->
  @@ -357,7 +357,7 @@
           <include name="james-server.xml"/>
         </zipfileset>
   
  -      <zipfileset dir="${conf.proposal.dir}" fullpath="conf/sqlResources.xml">
  +      <zipfileset dir="${conf.dir}" fullpath="conf/sqlResources.xml">
           <include name="sqlResources.xml"/>
         </zipfileset>
   
  @@ -724,6 +724,7 @@
   
     <target name="delete-dist" depends="setup-properties">
       <delete dir="${dist.dir}"/>
  +    <delete file="${build.lib}/${name}.sar"/>
     </target>
   </project>
   
  
  
  
  1.2       +76 -13    jakarta-james/proposals/imap/build-test.xml
  
  Index: build-test.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/build-test.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- build-test.xml	15 Jan 2002 08:38:25 -0000	1.1
  +++ build-test.xml	23 Jan 2002 21:53:31 -0000	1.2
  @@ -45,6 +45,7 @@
   
     <!-- Set the properties for build directory -->
     <property name="build.dir" value="build"/>
  +  <property name="build.classes" value="${build.dir}/classes"/>
     <property name="build.test.classes" value="${build.dir}/test/classes"/>
   
     <!-- Set the properties for source directories -->
  @@ -55,13 +56,15 @@
     <property name="test.dir" value="${proposal.dir}/test"/>
     <property name="lib.dir" value="lib"/>
   
  -  <!-- Set up the classpath -->
  -  <path id="project.class.path">
  -    <fileset dir="${lib.dir}">
  -        <include name="junit-3.7.jar"/>
  -        <include name="mail_1_2.jar"/>
  -        <include name="activation.jar"/>
  -    </fileset>
  +  <path id="test.class.path">
  +        <path location="${build.classes}"/>
  +        <fileset dir="${lib.dir}">
  +            <include name="junit-3.7.jar"/>
  +            <include name="mail_1_2.jar"/>
  +            <include name="activation.jar"/>
  +            <include name="avalon-framework-20011115.jar"/>
  +            <include name="phoenix-engine-20011230.jar"/>
  +        </fileset>
     </path>
   
     <!--
  @@ -71,16 +74,27 @@
     -->
     <target name="main" depends="compile" />
   
  +  <target name="clean">
  +    <delete dir="${build.test.classes}"/>
  +  </target>
  +
  +  <target name="clean-james">
  +    <ant antfile="proposals/imap/build-imap.xml" target="rebuild-dist"/>
  +  </target>
   
     <!-- Compiles the Functional tests -->
     <target name="compile">
  +    <echo message="${java.home}"/>
       <mkdir dir="${build.test.classes}"/>
   
       <javac destdir="${build.test.classes}"
              debug="${debug}"
              optimize="${optimize}"
              deprecation="${deprecation}">
  -      <classpath refid="project.class.path" />
  +
  +      <classpath refid="test.class.path">
  +      </classpath>
  +
         <src path="${test.dir}"/>
       </javac>
   
  @@ -90,8 +104,26 @@
           <exclude name="**/*.java"/>
         </fileset>
       </copy>
  +
  +    <!-- Load custom tasks -->
  +    <taskdef classname="org.apache.james.test.JamesTask" name="james">
  +        <classpath>
  +            <path location="${build.dir}/lib/james.bar"/>
  +            <path location="${build.test.classes}"/>
  +            <fileset dir="${lib.dir}">
  +                <include name="*.jar"/>
  +                <include name="logkit-1.0.jar"/>
  +                <include name="avalon-scratchpad-20011122.jar"/>
  +                <include name="avalon-excalibur-20011120.jar"/>
  +                <include name="avalon-framework-20011115.jar"/>
  +                <include name="phoenix-engine-20011230.jar"/>
  +                <include name="phoenix-client-20011230.jar"/>
  +            </fileset>
  +        </classpath>
  +    </taskdef>
  +
     </target>
  -  
  +
     <!-- Run the full set of Imap tests -->
     <target name="testimap" depends="testimap-init, testimap-nonauthenticated, testimap-authenticated, testimap-selected" />
   
  @@ -103,7 +135,7 @@
       <junit fork="yes">
           <classpath>
               <pathelement location="${build.test.classes}"/>
  -            <path refid="project.class.path"/>
  +            <path refid="test.class.path"/>
           </classpath>
           <formatter type="plain" usefile="false"/>
           <test name="org.apache.james.imapserver.InitialUsers"/>
  @@ -116,7 +148,7 @@
       <junit fork="yes">
           <classpath>
               <pathelement location="${build.test.classes}"/>
  -            <path refid="project.class.path"/>
  +            <path refid="test.class.path"/>
           </classpath>
           <formatter type="plain" usefile="false"/>
           <test name="org.apache.james.imapserver.TestNonAuthenticated"/>
  @@ -128,7 +160,7 @@
       <junit fork="yes">
           <classpath>
               <pathelement location="${build.test.classes}"/>
  -            <path refid="project.class.path"/>
  +            <path refid="test.class.path"/>
           </classpath>
           <formatter type="plain" usefile="false"/>
           <test name="org.apache.james.imapserver.TestAuthenticated"/>
  @@ -140,11 +172,42 @@
       <junit fork="yes">
           <classpath>
               <pathelement location="${build.test.classes}"/>
  -            <path refid="project.class.path"/>
  +            <path refid="test.class.path"/>
           </classpath>
           <formatter type="plain" usefile="false"/>
           <test name="org.apache.james.imapserver.TestSelected"/>
       </junit>
  +  </target>
  +
  +
  +  <!-- The following tasks attempt to use ANT to start/stop James. They don't really work at the moment. -->
  +  <target name="test-james" depends="clean-james, start-james, testimap, stop-james" />
  +
  +  <target name="start-james" depends="compile">
  +    <james action="start"/>
  +  </target>
  +
  +  <target name="stop-james" depends="compile">
  +    <james action="stop"/>
  +  </target>
  +
  +  <target name="start-stop" depends="compile">
  +    <james action="start-stop">
  +        <classpath>
  +            <path location="${build.dir}/lib/james.bar"/>
  +            <path location="${build.test.classes}"/>
  +            <fileset dir="${lib.dir}">
  +                <include name="*.bar"/>
  +                <include name="*.jar"/>
  +                <include name="logkit-1.0.jar"/>
  +                <include name="avalon-scratchpad-20011122.jar"/>
  +                <include name="avalon-excalibur-20011120.jar"/>
  +                <include name="avalon-framework-20011115.jar"/>
  +                <include name="phoenix-engine-20011230.jar"/>
  +                <include name="phoenix-client-20011230.jar"/>
  +            </fileset>
  +        </classpath>
  +    </james>
     </target>
   
   </project>
  
  
  
  1.3       +42 -23    jakarta-james/proposals/imap/java/org/apache/james/imapserver/BaseCommand.java
  
  Index: BaseCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/BaseCommand.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- BaseCommand.java	17 Jan 2002 06:09:00 -0000	1.2
  +++ BaseCommand.java	23 Jan 2002 21:53:31 -0000	1.3
  @@ -46,47 +46,66 @@
           }
           getLogger().debug(" decodeSet called for: " + rawSet);
           List response = new ArrayList();
  +
           int checkComma = rawSet.indexOf(",");
           if (checkComma == -1) {
  +            // No comma present
               int checkColon = rawSet.indexOf(":");
               if (checkColon == -1) {
  -                Integer seqNum = new Integer(rawSet.trim());
  -                if (seqNum.intValue() < 1) {
  -                    throw new IllegalArgumentException("Not a positive integer");
  -                } else {
  -                    response.add(seqNum);
  +                // No colon present (single integer)
  +                Integer seqNum;
  +                if ( rawSet.equals( "*" ) ) {
  +                    seqNum = new Integer( -1 );
  +                }
  +                else {
  +                    seqNum = new Integer(rawSet.trim());
  +                    if (seqNum.intValue() < 1) {
  +                        throw new IllegalArgumentException("Not a positive integer");
  +                    }
                   }
  -            } else {
  +                response.add(seqNum);
  +            }
  +            else {
  +                // Simple sequence
  +
  +                // Add the first number in the range.
                   Integer firstNum = new Integer(rawSet.substring(0, checkColon));
                   int first = firstNum.intValue();
  +                if ( first < 1  ) {
  +                    throw new IllegalArgumentException("Not a positive integer");
  +                }
  +                response.add( firstNum );
  +
                   Integer lastNum;
                   int last;
                   if (rawSet.indexOf("*") != -1) {
  -                    last = exists;
  -                    lastNum = new Integer(last);
  -                } else {
  +                    // Range from firstNum to '*'
  +                    // Add -1, to indicate unended range.
  +                    lastNum = new Integer( -1 );
  +                }
  +                else {
  +                    // Get the final num, and add all numbers in range.
                       lastNum = new Integer(rawSet.substring(checkColon + 1));
                       last = lastNum.intValue();
  -                }
  -                if (first < 1 || last < 1) {
  -                    throw new IllegalArgumentException("Not a positive integer");
  -                } else if (first < last) {
  -                    response.add(firstNum);
  -                    for (int i = (first + 1); i < last; i++) {
  +                    if ( last < 1 ) {
  +                        throw new IllegalArgumentException("Not a positive integer");
  +                    }
  +                    if ( last < first ) {
  +                        throw new IllegalArgumentException("Not an increasing range");
  +                    }
  +
  +                    for (int i = (first + 1); i <= last; i++) {
                           response.add(new Integer(i));
                       }
  -                    response.add(lastNum);
  -                } else if (first == last) {
  -                    response.add(firstNum);
  -                } else {
  -                    throw new IllegalArgumentException("Not an increasing range");
                   }
               }
   
  -        } else {
  +        }
  +        else {
  +            // Comma present, compound range.
               try {
  -                String firstRawSet = rawSet.substring(0, checkComma);
  -                String secondRawSet = rawSet.substring(checkComma + 1);
  +                String firstRawSet = rawSet.substring( 0, checkComma );
  +                String secondRawSet = rawSet.substring( checkComma + 1 );
                   response.addAll(decodeSet(firstRawSet, exists));
                   response.addAll(decodeSet(secondRawSet, exists));
               } catch (IllegalArgumentException e) {
  
  
  
  1.3       +1 -1      jakarta-james/proposals/imap/java/org/apache/james/imapserver/FolderRecord.java
  
  Index: FolderRecord.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/FolderRecord.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- FolderRecord.java	15 Jan 2002 08:38:25 -0000	1.2
  +++ FolderRecord.java	23 Jan 2002 21:53:32 -0000	1.3
  @@ -26,7 +26,7 @@
        *
        * @returns String mailbox hierarchical name including namespace
        */
  -    //String decodeMailboxName();
  +    //String readAstring();
   
       /**
        * Returns the user in whose namespace the mailbox existed.
  
  
  
  1.3       +0 -5      jakarta-james/proposals/imap/java/org/apache/james/imapserver/ImapConstants.java
  
  Index: ImapConstants.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/ImapConstants.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ImapConstants.java	15 Jan 2002 12:13:59 -0000	1.2
  +++ ImapConstants.java	23 Jan 2002 21:53:32 -0000	1.3
  @@ -17,16 +17,11 @@
   
       String SP = " ";
       String VERSION = "IMAP4rev1";
  -    String CAPABILITY_RESPONSE = "CAPABILITY " + VERSION; //add as implemented
   
       String AUTH_FAIL_MSG
               = "NO Command not authorized on this mailbox";
       String BAD_LISTRIGHTS_MSG
               = "BAD Command should be <tag> <LISTRIGHTS> <mailbox> <identifier>";
  -    String BAD_LIST_MSG
  -            = "BAD Command should be <tag> <LIST> <reference name> <mailbox>";
  -    String BAD_LSUB_MSG
  -            = "BAD Command should be <tag> <LSUB> <reference name> <mailbox>";
       String NO_NOTLOCAL_MSG
               = "NO Mailbox does not exist on this server";
   
  
  
  
  1.4       +9 -1      jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/AbstractAclCommand.java
  
  Index: AbstractAclCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/AbstractAclCommand.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- AbstractAclCommand.java	18 Jan 2002 02:48:35 -0000	1.3
  +++ AbstractAclCommand.java	23 Jan 2002 21:53:32 -0000	1.4
  @@ -9,12 +9,14 @@
   
   import org.apache.james.AccessControlException;
   import org.apache.james.AuthorizationException;
  +import org.apache.james.util.Assert;
   import org.apache.james.imapserver.ACLMailbox;
   import org.apache.james.imapserver.ImapRequest;
   import org.apache.james.imapserver.ImapSession;
   import org.apache.james.imapserver.ImapSessionState;
   
   import java.util.StringTokenizer;
  +import java.util.List;
   
   abstract class AbstractAclCommand extends AuthenticatedSelectedStateCommand
   {
  @@ -24,6 +26,12 @@
                                             ACLMailbox target, String folder )
               throws AccessControlException, AuthorizationException;
   
  +    protected boolean doProcess( ImapRequest request, ImapSession session, List argValues )
  +    {
  +        Assert.fail();
  +        return false;
  +    }
  +
       public boolean process( ImapRequest request, ImapSession session )
       {
           int arguments = request.arguments();
  @@ -35,7 +43,7 @@
               
           checkUsage( arguments, session );
               
  -        folder = decodeMailboxName( commandLine.nextToken() );
  +        folder = readAstring( commandLine );
               
           target = getMailbox( session, folder, command );
           if ( target == null ) return true;
  
  
  
  1.2       +10 -1     jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/AuthenticateCommand.java
  
  Index: AuthenticateCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/AuthenticateCommand.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AuthenticateCommand.java	15 Jan 2002 08:38:26 -0000	1.1
  +++ AuthenticateCommand.java	23 Jan 2002 21:53:32 -0000	1.2
  @@ -10,9 +10,18 @@
   import org.apache.james.imapserver.ImapRequest;
   import org.apache.james.imapserver.ImapSession;
   
  +import java.util.List;
  +
   class AuthenticateCommand extends NonAuthenticatedStateCommand
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    AuthenticateCommand()
  +    {
  +        this.commandName = "AUTHENTICATE";
  +
  +        this.getArgs().add( new AstringArgument( "auth-type" ) );
  +    }
  +
  +    public boolean doProcess( ImapRequest request, ImapSession session, List argValues )
       {
           session.noResponse( request.getCommand(), "Unsupported authentication mechanism" );
           return true;
  
  
  
  1.3       +5 -0      jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/AuthenticatedSelectedStateCommand.java
  
  Index: AuthenticatedSelectedStateCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/AuthenticatedSelectedStateCommand.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- AuthenticatedSelectedStateCommand.java	15 Jan 2002 12:14:00 -0000	1.2
  +++ AuthenticatedSelectedStateCommand.java	23 Jan 2002 21:53:32 -0000	1.3
  @@ -8,6 +8,11 @@
   package org.apache.james.imapserver.commands;
   
   import org.apache.james.imapserver.ImapSessionState;
  +import org.apache.james.imapserver.ImapRequest;
  +import org.apache.james.imapserver.ImapSession;
  +import org.apache.james.util.Assert;
  +
  +import java.util.List;
   
   
   /**
  
  
  
  1.3       +10 -1     jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/CapabilityCommand.java
  
  Index: CapabilityCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/CapabilityCommand.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- CapabilityCommand.java	15 Jan 2002 12:14:00 -0000	1.2
  +++ CapabilityCommand.java	23 Jan 2002 21:53:32 -0000	1.3
  @@ -11,9 +11,18 @@
   import org.apache.james.imapserver.ImapSession;
   import org.apache.james.imapserver.ImapSessionState;
   
  +import java.util.List;
  +
   class CapabilityCommand extends CommandTemplate
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    String CAPABILITY_RESPONSE = "CAPABILITY " + VERSION; //add as implemented
  +
  +    public CapabilityCommand()
  +    {
  +        this.commandName = "CAPABILITY";
  +    }
  +
  +    protected boolean doProcess( ImapRequest request, ImapSession session, List args )
       {
           session.untaggedResponse( CAPABILITY_RESPONSE );
           if ( session.getState() == ImapSessionState.SELECTED ) {
  
  
  
  1.2       +7 -1      jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/CheckCommand.java
  
  Index: CheckCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/CheckCommand.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- CheckCommand.java	15 Jan 2002 08:38:26 -0000	1.1
  +++ CheckCommand.java	23 Jan 2002 21:53:32 -0000	1.2
  @@ -11,10 +11,16 @@
   import org.apache.james.imapserver.ImapSession;
   
   import java.util.StringTokenizer;
  +import java.util.List;
   
   class CheckCommand extends SelectedStateCommand
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    public CheckCommand()
  +    {
  +        this.commandName = "CHECK";
  +    }
  +
  +    protected boolean doProcess( ImapRequest request, ImapSession session, List argValues )
       {
           int arguments = request.arguments();
           StringTokenizer commandLine = request.getCommandLine();
  
  
  
  1.3       +8 -1      jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/CloseCommand.java
  
  Index: CloseCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/CloseCommand.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- CloseCommand.java	15 Jan 2002 12:14:00 -0000	1.2
  +++ CloseCommand.java	23 Jan 2002 21:53:32 -0000	1.3
  @@ -11,9 +11,16 @@
   import org.apache.james.imapserver.ImapSession;
   import org.apache.james.imapserver.ImapSessionState;
   
  +import java.util.List;
  +
   class CloseCommand extends SelectedStateCommand
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    public CloseCommand()
  +    {
  +        this.commandName = "CLOSE";
  +    }
  +
  +    protected boolean doProcess( ImapRequest request, ImapSession session, List argValues )
       {
           try {
               session.getCurrentMailbox().expunge( session.getCurrentUser() );
  
  
  
  1.4       +100 -7    jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/CommandTemplate.java
  
  Index: CommandTemplate.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/CommandTemplate.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- CommandTemplate.java	18 Jan 2002 02:48:35 -0000	1.3
  +++ CommandTemplate.java	23 Jan 2002 21:53:32 -0000	1.4
  @@ -9,11 +9,81 @@
   
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
   import org.apache.james.AccessControlException;
  +import org.apache.james.util.Assert;
   import org.apache.james.imapserver.*;
   
  +import java.util.StringTokenizer;
  +import java.util.List;
  +import java.util.ArrayList;
  +import java.util.Iterator;
  +
   abstract class CommandTemplate 
           extends AbstractLogEnabled implements ImapCommand, ImapConstants
   {
  +    protected String commandName;
  +    private List args = new ArrayList();
  +
  +    protected String getCommand()
  +    {
  +        return this.commandName;
  +    }
  +
  +    /**
  +     * @return a List of <code>ImapArgument</code> objects.
  +     */
  +    protected List getArgs()
  +    {
  +        return this.args;
  +    }
  +
  +    protected String getExpectedMessage()
  +    {
  +        StringBuffer msg = new StringBuffer( "<tag> " );
  +        msg.append( getCommand() );
  +
  +        List args = getArgs();
  +        for ( Iterator iter = args.iterator(); iter.hasNext(); ) {
  +            msg.append( " " );
  +            ImapArgument arg = (ImapArgument) iter.next();
  +            msg.append( arg.format() );
  +        }
  +        return msg.toString();
  +    }
  +
  +    /**
  +     * Template methods for handling command processing.
  +     */
  +    public boolean process( ImapRequest request, ImapSession session )
  +    {
  +        StringTokenizer tokens = request.getCommandLine();
  +
  +        List args = getArgs();
  +        List argValues = new ArrayList();
  +
  +        for ( Iterator iter = args.iterator(); iter.hasNext(); ) {
  +            ImapArgument arg = (ImapArgument) iter.next();
  +            try {
  +                argValues.add( arg.parse( tokens ) );
  +            }
  +            catch ( Exception e ) {
  +                String badMsg = e.getMessage() + ": Command should be " + getExpectedMessage();
  +                session.badResponse( badMsg );
  +                return true;
  +            }
  +        }
  +
  +        if ( tokens.hasMoreTokens() ) {
  +            String badMsg = "Extra token found: Command should be " + getExpectedMessage();
  +            session.badResponse( badMsg );
  +            return true;
  +        }
  +
  +        return doProcess( request, session, argValues );
  +
  +    }
  +
  +    protected abstract boolean doProcess( ImapRequest request, ImapSession session, List argValues );
  +
       /**
        * By default, valid in any state (unless overridden by subclass.
        */ 
  @@ -57,18 +127,37 @@
           }
       }
   
  -    /**
  -     * Returns a full mailbox name, resolving the supplied name against the current location.
  -     */
  -    public String decodeMailboxName( String name )
  +    /** TODO - decode quoted strings properly, with escapes. */
  +    public static String readAstring( StringTokenizer tokens )
       {
  -        getLogger().debug( "Method decodeMailboxName called for " + name );
  -        return decodeAstring( name );
  +        if ( ! tokens.hasMoreTokens() ) {
  +            throw new RuntimeException( "Not enough tokens" );
  +        }
  +        String token = tokens.nextToken();
  +        Assert.isTrue( token.length() > 0 );
  +
  +        StringBuffer astring = new StringBuffer( token );
  +
  +        if ( astring.charAt(0) == '\"' ) {
  +            while ( astring.length() == 1 ||
  +                    astring.charAt( astring.length() - 1 ) != '\"' ) {
  +                if ( tokens.hasMoreTokens() ) {
  +                    astring.append( tokens.nextToken() );
  +                }
  +                else {
  +                    throw new RuntimeException( "Missing closing quote" );
  +                }
  +            }
  +            astring.deleteCharAt( 0 );
  +            astring.deleteCharAt( astring.length() - 1 );
  +        }
  +
  +        return astring.toString();
       }
   
  -    /** TODO - decode quoted strings properly, with escapes. */
       public String decodeAstring( String rawAstring )
       {
  +
           if ( rawAstring.length() == 0 ) {
               return rawAstring;
           }
  @@ -94,4 +183,8 @@
           }
       }
   
  +    public void setArgs( List args )
  +    {
  +        this.args = args;
  +    }
   }
  
  
  
  1.3       +18 -21    jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/CopyCommand.java
  
  Index: CopyCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/CopyCommand.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- CopyCommand.java	18 Jan 2002 02:48:35 -0000	1.2
  +++ CopyCommand.java	23 Jan 2002 21:53:32 -0000	1.3
  @@ -19,48 +19,45 @@
   
   class CopyCommand extends SelectedStateCommand
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    public CopyCommand()
       {
  -        int arguments = request.arguments();
  -        StringTokenizer commandLine = request.getCommandLine();
  -        String command = request.getCommand();
  +        this.commandName = "COPY";
   
  -        if ( arguments < 4 ) {
  -            session.badResponse( "Command should be <tag> <COPY> <message set> <mailbox name>" );
  -            return true;
  -        }
  -        List set = session.decodeSet( commandLine.nextToken(),
  -                              session.getCurrentMailbox().getExists() );
  -        getLogger().debug( "Fetching message set of size: " + set.size() );
  -        String targetFolder = decodeMailboxName( commandLine.nextToken() );
  +        this.getArgs().add( new SetArgument() );
  +        this.getArgs().add( new AstringArgument( "mailbox" ) );
  +    }
   
  +    protected boolean doProcess( ImapRequest request, ImapSession session, List argValues )
  +    {
  +        List set = (List) argValues.get( 0 );
  +        getLogger().debug( "Fetching message set of size: " + set.size() );
  +        String targetFolder = (String) argValues.get( 1 );
   
  -        ACLMailbox targetMailbox = getMailbox( session, targetFolder, command );
  +        ACLMailbox targetMailbox = getMailbox( session, targetFolder, this.commandName );
           if ( targetMailbox == null ) {
               return true;
           }
           try { // long tries clause against an AccessControlException
               if ( !session.getCurrentMailbox().hasInsertRights( session.getCurrentUser() ) ) {
  -                session.noResponse( command, "Insert access not granted." );
  +                session.noResponse( this.commandName, "Insert access not granted." );
                   return true;
               }
  -            for ( int i = 0; i < set.size(); i++ ) {
  -                int msn = ((Integer) set.get( i )).intValue();
  -                MessageAttributes attrs = session.getCurrentMailbox().getMessageAttributes( msn, session.getCurrentUser() );
  -            }
  +            // TODO - copy all messages in set.
  +            int msn = ((Integer)set.get( 0 ) ).intValue();
  +            session.getCurrentMailbox().getMessageAttributes( msn, session.getCurrentUser() );
           }
           catch ( AccessControlException ace ) {
  -            session.noResponse( command, "No such mailbox." );
  +            session.noResponse( this.commandName, "No such mailbox." );
               session.logACE( ace );
               return true;
           }
           catch ( AuthorizationException aze ) {
  -            session.noResponse( command, "You do not have the rights to expunge mailbox: " + targetFolder );
  +            session.noResponse( this.commandName, "You do not have the rights to expunge mailbox: " + targetFolder );
               session.logAZE( aze );
               return true;
           }
   
  -        session.okResponse( command );
  +        session.okResponse( this.commandName );
           return true;
       }
   }
  
  
  
  1.3       +10 -10    jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/CreateCommand.java
  
  Index: CreateCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/CreateCommand.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- CreateCommand.java	15 Jan 2002 12:14:00 -0000	1.2
  +++ CreateCommand.java	23 Jan 2002 21:53:32 -0000	1.3
  @@ -12,22 +12,22 @@
   import org.apache.james.imapserver.*;
   
   import java.util.StringTokenizer;
  +import java.util.List;
   
   class CreateCommand extends AuthenticatedSelectedStateCommand
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    public CreateCommand()
       {
  -        int arguments = request.arguments();
  -        StringTokenizer commandLine = request.getCommandLine();
  -        String command = request.getCommand();
  -        String folder = null;
  +        this.commandName = "CREATE";
  +        this.getArgs().add( new AstringArgument( "mailbox" ) );
  +    }
  +
  +    protected boolean doProcess( ImapRequest request, ImapSession session, List argValues )
  +    {
  +        String command = this.commandName;
  +        String folder = (String) argValues.get( 0 );
   
  -        if ( arguments != 1 ) {
  -            session.badResponse( "Command should be <tag> <CREATE> <mailbox>" );
  -            return true;
  -        }
           try {
  -            folder = decodeMailboxName( commandLine.nextToken() );
               if ( session.getCurrentFolder() == folder ) {
                   session.noResponse( command, "Folder exists and is selected." );
                   return true;
  
  
  
  1.4       +13 -11    jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/DeleteCommand.java
  
  Index: DeleteCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/DeleteCommand.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- DeleteCommand.java	18 Jan 2002 02:48:35 -0000	1.3
  +++ DeleteCommand.java	23 Jan 2002 21:53:32 -0000	1.4
  @@ -15,22 +15,24 @@
   import org.apache.james.imapserver.MailboxException;
   
   import java.util.StringTokenizer;
  +import java.util.List;
   
   class DeleteCommand extends AuthenticatedSelectedStateCommand
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    public DeleteCommand()
       {
  -        int arguments = request.arguments();
  -        StringTokenizer commandLine = request.getCommandLine();
  -        String command = request.getCommand();
  +        this.commandName = "DELETE";
   
  -        String folder;
  -        if ( arguments != 1 ) {
  -            session.badResponse( "Command should be <tag> <DELETE> <mailbox>" );
  -            return true;
  -        }
  -        folder = decodeMailboxName( commandLine.nextToken() );
  -        if ( session.getCurrentFolder() == folder ) {
  +        this.getArgs().add( new AstringArgument( "mailbox" ) );
  +    }
  +
  +    public boolean doProcess( ImapRequest request, ImapSession session, List argValues )
  +    {
  +        String command = this.getCommand();
  +
  +        String folder = (String) argValues.get( 0 );
  +
  +        if ( session.getCurrentFolder().equals( folder ) ) {
               session.noResponse( command, "You can't delete a folder while you have it selected." );
               return true;
           }
  
  
  
  1.2       +8 -4      jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/ExpungeCommand.java
  
  Index: ExpungeCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/ExpungeCommand.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ExpungeCommand.java	15 Jan 2002 08:38:26 -0000	1.1
  +++ ExpungeCommand.java	23 Jan 2002 21:53:32 -0000	1.2
  @@ -13,14 +13,18 @@
   import org.apache.james.imapserver.ImapSession;
   
   import java.util.StringTokenizer;
  +import java.util.List;
   
   class ExpungeCommand extends SelectedStateCommand
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    public ExpungeCommand()
       {
  -        int arguments = request.arguments();
  -        StringTokenizer commandLine = request.getCommandLine();
  -        String command = request.getCommand();
  +        this.commandName = "EXPUNGE";
  +    }
  +
  +    public boolean doProcess( ImapRequest request, ImapSession session, List argValues )
  +    {
  +        String command = this.getCommand();
   
           try {
               if ( session.getCurrentMailbox().expunge( session.getCurrentUser() ) ) {
  
  
  
  1.3       +1 -0      jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/ImapCommand.java
  
  Index: ImapCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/ImapCommand.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ImapCommand.java	15 Jan 2002 12:14:00 -0000	1.2
  +++ ImapCommand.java	23 Jan 2002 21:53:32 -0000	1.3
  @@ -14,5 +14,6 @@
   public interface ImapCommand
   {
       boolean validForState( ImapSessionState state );
  +
       boolean process( ImapRequest request, ImapSession session );
   }
  
  
  
  1.3       +4 -4      jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/ImapCommandFactory.java
  
  Index: ImapCommandFactory.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/ImapCommandFactory.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ImapCommandFactory.java	18 Jan 2002 02:48:35 -0000	1.2
  +++ ImapCommandFactory.java	23 Jan 2002 21:53:32 -0000	1.3
  @@ -43,15 +43,15 @@
   
           // Commands valid in AUTHENTICATED or SELECTED state.
           // RFC2060: SELECT, EXAMINE, CREATE, DELETE, RENAME, SUBSCRIBE, UNSUBSCRIBE, LIST, LSUB, STATUS, and APPEND
  -        _imapCommands.put( "SELECT", SelectOrExamineCommand.class );
  -        _imapCommands.put( "EXAMINE", SelectOrExamineCommand.class );
  +        _imapCommands.put( "SELECT", SelectCommand.class );
  +        _imapCommands.put( "EXAMINE", ExamineCommand.class );
           _imapCommands.put( "CREATE", CreateCommand.class );
           _imapCommands.put( "DELETE", DeleteCommand.class );
           _imapCommands.put( "RENAME", RenameCommand.class );
           _imapCommands.put( "SUBSCRIBE", SubscribeCommand.class );
           _imapCommands.put( "UNSUBSCRIBE", UnsubscribeCommand.class );
  -        _imapCommands.put( "LIST", ListOrLsubCommand.class );
  -        _imapCommands.put( "LSUB", ListOrLsubCommand.class );
  +        _imapCommands.put( "LIST", ListCommand.class );
  +        _imapCommands.put( "LSUB", LsubCommand.class );
           _imapCommands.put( "STATUS", StatusCommand.class );
           _imapCommands.put( "APPEND", NotImplementedCommand.class );
           // RFC2342 NAMESPACE
  
  
  
  1.2       +7 -1      jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/InvalidCommand.java
  
  Index: InvalidCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/InvalidCommand.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- InvalidCommand.java	15 Jan 2002 08:38:26 -0000	1.1
  +++ InvalidCommand.java	23 Jan 2002 21:53:32 -0000	1.2
  @@ -10,9 +10,15 @@
   
   import org.apache.james.imapserver.ImapRequest;
   import org.apache.james.imapserver.ImapSession;
  +import org.apache.james.imapserver.ImapSessionState;
   
  -class InvalidCommand extends CommandTemplate
  +class InvalidCommand implements ImapCommand
   {
  +    public boolean validForState( ImapSessionState state )
  +    {
  +        return true;
  +    }
  +
       public boolean process( ImapRequest request, ImapSession session )
       {
           session.badResponse( "Protocol error" );
  
  
  
  1.3       +17 -8     jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/LoginCommand.java
  
  Index: LoginCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/LoginCommand.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- LoginCommand.java	15 Jan 2002 12:14:00 -0000	1.2
  +++ LoginCommand.java	23 Jan 2002 21:53:32 -0000	1.3
  @@ -12,17 +12,25 @@
   import org.apache.james.imapserver.ImapSession;
   import org.apache.james.imapserver.ImapSessionState;
   
  +import java.util.StringTokenizer;
  +import java.util.List;
  +
   class LoginCommand extends NonAuthenticatedStateCommand
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    LoginCommand()
       {
  -        if ( request.arguments() != 2 ) {
  -            String badMsg = "Command should be <tag> <LOGIN> <username> <password>";
  -            session.badResponse( badMsg );
  -            return true;
  -        }
  -        session.setCurrentUser( decodeAstring( request.getCommandLine().nextToken() ) );
  -        String password = decodeAstring( request.getCommandLine().nextToken() );
  +        this.commandName = "LOGIN";
  +
  +        this.getArgs().add( new AstringArgument( "username" ) );
  +        this.getArgs().add( new AstringArgument( "password" ) );
  +    }
  +
  +    protected boolean doProcess( ImapRequest request, ImapSession session, List argValues )
  +    {
  +        String userName = (String) argValues.get(0);
  +        String password = (String) argValues.get(1);
  +
  +        session.setCurrentUser( userName );
           if ( session.getUsers().test( session.getCurrentUser(), password ) ) {
               session.getSecurityLogger().info( "Login successful for " + session.getCurrentUser() + " from  "
                                    + session.getRemoteHost() + "(" + session.getRemoteIP() + ")" );
  @@ -74,6 +82,7 @@
   
   
           } // failed password test
  +
           // We should add ability to monitor attempts to login
           session.noResponse( request.getCommand() );
           session.getSecurityLogger().error( "Failed attempt to use Login command for account "
  
  
  
  1.2       +8 -1      jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/LogoutCommand.java
  
  Index: LogoutCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/LogoutCommand.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- LogoutCommand.java	15 Jan 2002 08:38:26 -0000	1.1
  +++ LogoutCommand.java	23 Jan 2002 21:53:32 -0000	1.2
  @@ -11,9 +11,16 @@
   import org.apache.james.imapserver.ImapRequest;
   import org.apache.james.imapserver.ImapSession;
   
  +import java.util.List;
  +
   class LogoutCommand extends CommandTemplate
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    public LogoutCommand()
  +    {
  +        this.commandName = "LOGOUT";
  +    }
  +
  +    public boolean doProcess( ImapRequest request, ImapSession session, List argValues )
       {
           session.setConnectionClosed( session.closeConnection( NORMAL_CLOSE, "", "" ) );
           return false;
  
  
  
  1.3       +8 -1      jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/NamespaceCommand.java
  
  Index: NamespaceCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/NamespaceCommand.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- NamespaceCommand.java	15 Jan 2002 12:14:00 -0000	1.2
  +++ NamespaceCommand.java	23 Jan 2002 21:53:32 -0000	1.3
  @@ -12,9 +12,16 @@
   import org.apache.james.imapserver.ImapSession;
   import org.apache.james.imapserver.ImapSessionState;
   
  +import java.util.List;
  +
   class NamespaceCommand extends AuthenticatedSelectedStateCommand
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    public NamespaceCommand()
  +    {
  +        this.commandName = "NAMESPACE";
  +    }
  +
  +    public boolean doProcess( ImapRequest request, ImapSession session, List argValues )
       {
           String namespaces = session.getImapSystem().getNamespaces( session.getCurrentUser() );
           session.untaggedResponse( "NAMESPACE " + namespaces );
  
  
  
  1.3       +5 -0      jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/NonAuthenticatedStateCommand.java
  
  Index: NonAuthenticatedStateCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/NonAuthenticatedStateCommand.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- NonAuthenticatedStateCommand.java	15 Jan 2002 12:14:00 -0000	1.2
  +++ NonAuthenticatedStateCommand.java	23 Jan 2002 21:53:32 -0000	1.3
  @@ -8,12 +8,17 @@
   package org.apache.james.imapserver.commands;
   
   import org.apache.james.imapserver.ImapSessionState;
  +import org.apache.james.imapserver.ImapRequest;
  +import org.apache.james.imapserver.ImapSession;
  +
  +import java.util.StringTokenizer;
   
   /**
    * A base class for ImapCommands only valid in the NON_AUTHENTICATED state.
    */
   abstract class NonAuthenticatedStateCommand extends CommandTemplate
   {
  +
       /**
        * By default, valid in any state (unless overridden by subclass.
        */
  
  
  
  1.3       +8 -1      jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/NoopCommand.java
  
  Index: NoopCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/NoopCommand.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- NoopCommand.java	15 Jan 2002 12:14:00 -0000	1.2
  +++ NoopCommand.java	23 Jan 2002 21:53:32 -0000	1.3
  @@ -12,9 +12,16 @@
   import org.apache.james.imapserver.ImapSession;
   import org.apache.james.imapserver.ImapSessionState;
   
  +import java.util.List;
  +
   class NoopCommand extends CommandTemplate
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    public NoopCommand()
  +    {
  +        this.commandName = "NOOP";
  +    }
  +
  +    public boolean doProcess( ImapRequest request, ImapSession session, List argValues )
       {
           if ( session.getState() == ImapSessionState.SELECTED ) {
               session.checkSize();
  
  
  
  1.2       +7 -1      jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/NotImplementedCommand.java
  
  Index: NotImplementedCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/NotImplementedCommand.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- NotImplementedCommand.java	15 Jan 2002 08:38:26 -0000	1.1
  +++ NotImplementedCommand.java	23 Jan 2002 21:53:32 -0000	1.2
  @@ -10,9 +10,15 @@
   
   import org.apache.james.imapserver.ImapRequest;
   import org.apache.james.imapserver.ImapSession;
  +import org.apache.james.imapserver.ImapSessionState;
   
  -class NotImplementedCommand extends CommandTemplate
  +class NotImplementedCommand implements ImapCommand
   {
  +    public boolean validForState( ImapSessionState state )
  +    {
  +        return true;
  +    }
  +
       public boolean process( ImapRequest request, ImapSession session )
       {
           session.notImplementedResponse(request.getCommand() );
  
  
  
  1.4       +14 -11    jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/RenameCommand.java
  
  Index: RenameCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/RenameCommand.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- RenameCommand.java	18 Jan 2002 02:48:35 -0000	1.3
  +++ RenameCommand.java	23 Jan 2002 21:53:32 -0000	1.4
  @@ -14,22 +14,25 @@
   import org.apache.james.imapserver.MailboxException;
   
   import java.util.StringTokenizer;
  +import java.util.List;
   
   class RenameCommand extends AuthenticatedSelectedStateCommand
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    public RenameCommand()
       {
  -        int arguments = request.arguments();
  -        StringTokenizer commandLine = request.getCommandLine();
  -        String command = request.getCommand();
  +        this.commandName = "RENAME";
  +
  +        this.getArgs().add( new AstringArgument( "oldName" ) );
  +        this.getArgs().add( new AstringArgument( "newName" ) );
  +    }
  +
  +    public boolean doProcess( ImapRequest request, ImapSession session, List argValues )
  +    {
  +        String command = this.getCommand();
  +
  +        String folder = (String) argValues.get( 0 );
  +        String newName = (String) argValues.get( 1 );
   
  -        String folder;
  -        if ( arguments != 4 ) {
  -            session.badResponse( "Command should be <tag> <RENAME> <oldname> <newname>" );
  -            return true;
  -        }
  -        folder = decodeMailboxName( commandLine.nextToken() );
  -        String newName = decodeMailboxName( commandLine.nextToken() );
           if ( session.getCurrentFolder() == folder ) {
               session.noResponse( command, "You can't rename a folder while you have it selected." );
               return true;
  
  
  
  1.3       +5 -0      jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/SelectedStateCommand.java
  
  Index: SelectedStateCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/SelectedStateCommand.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- SelectedStateCommand.java	15 Jan 2002 12:14:00 -0000	1.2
  +++ SelectedStateCommand.java	23 Jan 2002 21:53:32 -0000	1.3
  @@ -8,6 +8,11 @@
   package org.apache.james.imapserver.commands;
   
   import org.apache.james.imapserver.ImapSessionState;
  +import org.apache.james.imapserver.ImapRequest;
  +import org.apache.james.imapserver.ImapSession;
  +import org.apache.james.util.Assert;
  +
  +import java.util.List;
   
   /**
    * A base class for ImapCommands only valid in the SELECTED state.
  
  
  
  1.4       +13 -31    jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/StatusCommand.java
  
  Index: StatusCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/StatusCommand.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- StatusCommand.java	18 Jan 2002 02:48:35 -0000	1.3
  +++ StatusCommand.java	23 Jan 2002 21:53:32 -0000	1.4
  @@ -19,39 +19,21 @@
   
   class StatusCommand extends AuthenticatedSelectedStateCommand
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    public StatusCommand()
       {
  -        int arguments = request.arguments();
  -        StringTokenizer commandLine = request.getCommandLine();
  -        String command = request.getCommand();
  +        this.commandName = "STATUS";
  +
  +        this.getArgs().add( "mailbox" );
  +        this.getArgs().add( "status data item" );
  +    }
  +
  +    protected boolean doProcess( ImapRequest request, ImapSession session, List argValues )
  +    {
  +        String command = this.getCommand();
  +
  +        String folder = (String) argValues.get( 0 );
  +        List dataNames = (List) argValues.get( 1 );
   
  -        String folder;
  -        if ( arguments < 4 ) {
  -            session.badResponse( "Command should be <tag> <STATUS> <mailboxname> (status data items)" );
  -            return true;
  -        }
  -        folder = decodeMailboxName( commandLine.nextToken() );
  -        List dataNames = new ArrayList();
  -        String attr = commandLine.nextToken();
  -        if ( !attr.startsWith( "(" ) ) { //single attr
  -            session.badResponse( "Command should be <tag> <STATUS> <mailboxname> (status data items)" );
  -            return true;
  -        }
  -        else if ( attr.endsWith( ")" ) ) { //single attr in paranthesis
  -            dataNames.add( attr.substring( 1, attr.length() - 1 ) );
  -        }
  -        else { // multiple attrs
  -            dataNames.add( attr.substring( 1 ).trim() );
  -            while ( commandLine.hasMoreTokens() ) {
  -                attr = commandLine.nextToken();
  -                if ( attr.endsWith( ")" ) ) {
  -                    dataNames.add( attr.substring( 0, attr.length() - 1 ) );
  -                }
  -                else {
  -                    dataNames.add( attr );
  -                }
  -            }
  -        }
           try {
               String response = session.getImapHost().getMailboxStatus( session.getCurrentUser(), folder,
                                                            dataNames );
  
  
  
  1.4       +11 -10    jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/SubscribeCommand.java
  
  Index: SubscribeCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/SubscribeCommand.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- SubscribeCommand.java	18 Jan 2002 02:48:35 -0000	1.3
  +++ SubscribeCommand.java	23 Jan 2002 21:53:32 -0000	1.4
  @@ -14,21 +14,22 @@
   import org.apache.james.imapserver.MailboxException;
   
   import java.util.StringTokenizer;
  +import java.util.List;
   
   class SubscribeCommand extends AuthenticatedSelectedStateCommand
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    public SubscribeCommand()
       {
  -        int arguments = request.arguments();
  -        StringTokenizer commandLine = request.getCommandLine();
  -        String command = request.getCommand();
  +        this.commandName = "SUBSCRIBE";
   
  -        String folder;
  -        if ( arguments != 1 ) {
  -            session.badResponse( "Command should be <tag> <SUBSCRIBE> <mailbox>" );
  -            return true;
  -        }
  -        folder = decodeMailboxName( commandLine.nextToken() );
  +        this.getArgs().add( new AstringArgument( "mailbox" ) );
  +    }
  +
  +    protected boolean doProcess( ImapRequest request, ImapSession session, List argValues )
  +    {
  +        String command = this.getCommand();
  +
  +        String folder = (String) argValues.get( 0 );
   
           try {
               if ( session.getImapHost().subscribe( session.getCurrentUser(), folder ) ) {
  
  
  
  1.3       +9 -5      jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/UidCommand.java
  
  Index: UidCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/UidCommand.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- UidCommand.java	18 Jan 2002 02:48:35 -0000	1.2
  +++ UidCommand.java	23 Jan 2002 21:53:32 -0000	1.3
  @@ -7,15 +7,19 @@
    */
   package org.apache.james.imapserver.commands;
   
  -import org.apache.james.imapserver.CommandFetch;
  -import org.apache.james.imapserver.CommandStore;
  -import org.apache.james.imapserver.ImapRequest;
  -import org.apache.james.imapserver.ImapSession;
  +import org.apache.james.imapserver.*;
  +import org.apache.james.util.Assert;
   
   import java.util.StringTokenizer;
  +import java.util.List;
   
  -class UidCommand extends SelectedStateCommand
  +class UidCommand implements ImapCommand
   {
  +    public boolean validForState( ImapSessionState state )
  +    {
  +        return ( state == ImapSessionState.SELECTED );
  +    }
  +
       public boolean process( ImapRequest request, ImapSession session )
       {
           int arguments = request.arguments();
  
  
  
  1.4       +11 -10    jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/UnsubscribeCommand.java
  
  Index: UnsubscribeCommand.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/UnsubscribeCommand.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- UnsubscribeCommand.java	18 Jan 2002 02:48:35 -0000	1.3
  +++ UnsubscribeCommand.java	23 Jan 2002 21:53:32 -0000	1.4
  @@ -14,21 +14,22 @@
   import org.apache.james.imapserver.MailboxException;
   
   import java.util.StringTokenizer;
  +import java.util.List;
   
   class UnsubscribeCommand extends AuthenticatedSelectedStateCommand
   {
  -    public boolean process( ImapRequest request, ImapSession session )
  +    public UnsubscribeCommand()
       {
  -        int arguments = request.arguments();
  -        StringTokenizer commandLine = request.getCommandLine();
  -        String command = request.getCommand();
  +        this.commandName = "UNSUBSCRIBE";
   
  -        String folder;
  -        if ( arguments != 1 ) {
  -            session.badResponse( "Command should be <tag> <UNSUBSCRIBE> <mailbox>" );
  -            return true;
  -        }
  -        folder = decodeMailboxName( commandLine.nextToken() );
  +        this.getArgs().add( new AstringArgument( "mailbox" ) );
  +    }
  +
  +    protected boolean doProcess( ImapRequest request, ImapSession session, List argValues )
  +    {
  +        String command = this.getCommand();
  +
  +        String folder = (String) argValues.get( 0 );
   
           try {
               if ( session.getImapHost().unsubscribe( session.getCurrentUser(), folder ) ) {
  
  
  
  1.1                  jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/AstringArgument.java
  
  Index: AstringArgument.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.imapserver.commands;
  
  import org.apache.james.util.Assert;
  
  import java.util.StringTokenizer;
  
  class AstringArgument implements ImapArgument
  {
      private String name;
      private boolean isFinal;
  
      public AstringArgument( String name )
      {
          this.name = name;
      }
  
      public Object parse( StringTokenizer tokens )
              throws Exception
      {
          // TODO: do this properly - need to check for disallowed characters.
  
          if ( ! tokens.hasMoreTokens() ) {
              throw new Exception( "Missing argument <" + this.name + ">");
          }
          String token = tokens.nextToken();
          Assert.isTrue( token.length() > 0 );
  
          StringBuffer astring = new StringBuffer( token );
  
          if ( astring.charAt(0) == '\"' ) {
              while ( astring.length() == 1 ||
                      astring.charAt( astring.length() - 1 ) != '\"' ) {
                  if ( tokens.hasMoreTokens() ) {
                      astring.append( " " );
                      astring.append( tokens.nextToken() );
                  }
                  else {
                      throw new Exception( "Missing closing quote for <" + this.name + ">" );
                  }
              }
              astring.deleteCharAt( 0 );
              astring.deleteCharAt( astring.length() - 1 );
          }
  
          return astring.toString();
      }
  
      public String format()
      {
          return "<" + this.name + ">";
      }
  
  }
  
  
  
  1.1                  jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/ExamineCommand.java
  
  Index: ExamineCommand.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.imapserver.commands;
  
  final class ExamineCommand extends SelectCommand
  {
      public ExamineCommand()
      {
          super();
          this.commandName = "EXAMINE";
      }
  }
  
  
  
  1.1                  jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/ImapArgument.java
  
  Index: ImapArgument.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.imapserver.commands;
  
  import org.apache.james.imapserver.ImapSession;
  
  import java.util.StringTokenizer;
  
  public interface ImapArgument
  {
      Object parse( StringTokenizer tokens ) throws Exception;
  
      String format();
  }
  
  
  
  1.1                  jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/ListArgument.java
  
  Index: ListArgument.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.imapserver.commands;
  
  import java.util.StringTokenizer;
  import java.util.ArrayList;
  import java.util.List;
  
  final class ListArgument implements ImapArgument
  {
      private String type;
  
      public ListArgument( String type )
      {
          this.type = type;
      }
  
      public Object parse( StringTokenizer tokens ) throws Exception
      {
          // TODO: implement this properly.
          String attr = tokens.nextToken();
          List dataNames = new ArrayList();
  
          if ( !attr.startsWith( "(" ) ) {
              throw new Exception( "Missing '(': " );
          }
          else if ( attr.endsWith( ")" ) ) { //single attr in paranthesis
              dataNames.add( attr.substring( 1, attr.length() - 1 ) );
          }
          else { // multiple attrs
              dataNames.add( attr.substring( 1 ).trim() );
              while ( tokens.hasMoreTokens() ) {
                  attr = tokens.nextToken();
                  if ( attr.endsWith( ")" ) ) {
                      dataNames.add( attr.substring( 0, attr.length() - 1 ) );
                  }
                  else {
                      dataNames.add( attr );
                  }
              }
          }
  
          return dataNames;
      }
  
      public String format()
      {
          return "( <" + this.type + ">+ )";
      }
  }
  
  
  
  1.1                  jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/ListCommand.java
  
  Index: ListCommand.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.imapserver.commands;
  
  import org.apache.james.AccessControlException;
  import org.apache.james.imapserver.ImapRequest;
  import org.apache.james.imapserver.ImapSession;
  import org.apache.james.imapserver.ImapSessionState;
  import org.apache.james.imapserver.MailboxException;
  
  import java.util.Collection;
  import java.util.Iterator;
  import java.util.StringTokenizer;
  import java.util.List;
  
  class ListCommand extends AuthenticatedSelectedStateCommand
  {
      public ListCommand()
      {
          this.commandName = "LIST";
  
          this.getArgs().add( new AstringArgument( "reference name" ) );
          this.getArgs().add( new AstringArgument( "mailbox" ) );
      }
  
      protected boolean doProcess( ImapRequest request, ImapSession session, List argValues )
      {
          String command = this.commandName;
  
          boolean subscribeOnly;
          if ( command.equalsIgnoreCase( "LIST" ) ) {
              subscribeOnly = false;
          }
          else {
              subscribeOnly = true;
          }
  
          String reference = (String) argValues.get( 0 );
          String folder = (String) argValues.get( 1 );
  
          Collection list = null;
          try {
              list = session.getImapHost().listMailboxes( session.getCurrentUser(), reference, folder,
                                                          subscribeOnly );
              if ( list == null ) {
                  session.noResponse( command, " unable to interpret mailbox" );
              }
              else if ( list.size() == 0 ) {
                  getLogger().debug( "List request matches zero mailboxes: " + request.getCommandRaw() );
                  session.okResponse( command );
              }
              else {
                  Iterator it = list.iterator();
                  while ( it.hasNext() ) {
                      String listResponse = (String) it.next();
                      session.getOut().println( UNTAGGED + SP + command.toUpperCase()
                                                 + SP + listResponse );
                      getLogger().debug( UNTAGGED + SP + command.toUpperCase()
                                         + SP + listResponse );
                  }
                  session.okResponse( command );
              }
          }
          catch ( MailboxException mbe ) {
              if ( mbe.isRemote() ) {
                  session.noResponse( command, "[REFERRAL "
                                             + mbe.getRemoteServer() + "]"
                                             + SP + "Wrong server. Try remote." );
              }
              else {
                  session.noResponse( command, "No such mailbox" );
              }
              return true;
          }
          catch ( AccessControlException ace ) {
              session.noResponse( command, "No such mailbox" );
              session.logACE( ace );
              return true;
          }
  
          if ( session.getState() == ImapSessionState.SELECTED ) {
              session.checkSize();
              session.checkExpunge();
          }
          return true;
      }
  }
  
  
  
  1.1                  jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/LsubCommand.java
  
  Index: LsubCommand.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.imapserver.commands;
  
  final class LsubCommand extends ListCommand
  {
      public LsubCommand()
      {
          super();
          this.commandName = "LSUB";
      }
  }
  
  
  
  1.1                  jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/SelectCommand.java
  
  Index: SelectCommand.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.imapserver.commands;
  
  import org.apache.james.AccessControlException;
  import org.apache.james.imapserver.ACLMailbox;
  import org.apache.james.imapserver.ImapRequest;
  import org.apache.james.imapserver.ImapSession;
  import org.apache.james.imapserver.ImapSessionState;
  
  import java.util.StringTokenizer;
  import java.util.List;
  
  class SelectCommand extends AuthenticatedSelectedStateCommand
  {
      public SelectCommand()
      {
          this.commandName = "SELECT";
  
          this.getArgs().add( new AstringArgument( "mailbox" ) );
      }
  
      protected boolean doProcess( ImapRequest request, ImapSession session, List argValues )
      {
          String command = this.getCommand();
  
          // selecting a mailbox deselects current mailbox,
          // even if this select fails
          if ( session.getState() == ImapSessionState.SELECTED ) {
              session.getCurrentMailbox().removeMailboxEventListener( session );
              session.getImapHost().releaseMailbox( session.getCurrentUser(), session.getCurrentMailbox() );
              session.setState( ImapSessionState.AUTHENTICATED );
              session.setCurrentMailbox( null );
              session.setCurrentIsReadOnly( false );
          }
  
          String folder = (String) argValues.get( 0 );
          ACLMailbox mailbox = getMailbox( session, folder, command );
          if ( mailbox == null ) {
              return true;
          }
          else {
              session.setCurrentMailbox( mailbox );
          }
  
          try { // long tries clause against an AccessControlException
              if ( !session.getCurrentMailbox().hasReadRights( session.getCurrentUser() ) ) {
                  session.noResponse( command, "Read access not granted." );
                  return true;
              }
              if ( command.equalsIgnoreCase( "SELECT" ) ) {
                  if ( !session.getCurrentMailbox().isSelectable( session.getCurrentUser() ) ) {
                      session.noResponse( "Mailbox exists but is not selectable" );
                      return true;
                  }
              }
  
              // Have mailbox with at least read rights. Server setup.
              session.getCurrentMailbox().addMailboxEventListener( session );
              session.setCurrentFolder( folder );
              session.setState( ImapSessionState.SELECTED );
              getLogger().debug( "Current folder for user " + session.getCurrentUser() + " from "
                                 + session.getRemoteHost() + "(" + session.getRemoteIP() + ") is "
                                 + session.getCurrentFolder() );
  
              // Inform client
              session.getOut().println( UNTAGGED + SP + "FLAGS ("
                                         + session.getCurrentMailbox().getSupportedFlags() + ")" );
              if ( !session.getCurrentMailbox().allFlags( session.getCurrentUser() ) ) {
                  session.untaggedResponse( " [PERMANENTFLAGS ("
                                             + session.getCurrentMailbox().getPermanentFlags( session.getCurrentUser() )
                                             + ") ]" );
              }
              session.checkSize();
              session.getOut().println( UNTAGGED + SP + OK + " [UIDVALIDITY "
                                         + session.getCurrentMailbox().getUIDValidity() + "]" );
              int oldestUnseen = session.getCurrentMailbox().getOldestUnseen( session.getCurrentUser() );
              if ( oldestUnseen > 0 ) {
                  session.getOut().println( UNTAGGED + SP + OK + " [UNSEEN "
                                             + oldestUnseen + "] " + oldestUnseen + " is the first unseen" );
              }
              else {
                  session.getOut().println( UNTAGGED + SP + OK + " No unseen messages" );
              }
              session.setSequence( session.getCurrentMailbox().listUIDs( session.getCurrentUser() ));
  
              if ( command.equalsIgnoreCase( "EXAMINE" ) ) {
                  session.setCurrentIsReadOnly( true );
  
                  session.okResponse("[READ-ONLY] " + command );
                  return true;
  
              }
              else if ( session.getCurrentMailbox().isReadOnly( session.getCurrentUser() ) ) {
                  session.setCurrentIsReadOnly( true );
                  session.okResponse( "[READ-ONLY] " + command );
                  return true;
              }
              session.okResponse( "[READ-WRITE] " + command );
              return true;
          }
          catch ( AccessControlException ace ) {
              session.noResponse( command, "No such mailbox." );
              session.logACE( ace );
              return true;
          }
      }
  }
  
  
  
  1.1                  jakarta-james/proposals/imap/java/org/apache/james/imapserver/commands/SetArgument.java
  
  Index: SetArgument.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.imapserver.commands;
  
  import java.util.ArrayList;
  import java.util.List;
  import java.util.StringTokenizer;
  
  final class SetArgument implements ImapArgument
  {
      public Object parse( StringTokenizer tokens ) throws Exception
      {
          if ( !tokens.hasMoreTokens() ) {
              throw new Exception( "Missing argument " + format() );
          }
  
          return tokens.nextToken();
      }
  
      private List parseSet( String rawSet )
      {
          List response = new ArrayList();
  
          int checkComma = rawSet.indexOf( "," );
          if ( checkComma == -1 ) {
              // No comma present
              int checkColon = rawSet.indexOf( ":" );
              if ( checkColon == -1 ) {
                  // No colon present (single integer)
                  Integer seqNum;
                  if ( rawSet.equals( "*" ) ) {
                      seqNum = new Integer( -1 );
                  }
                  else {
                      seqNum = new Integer( rawSet.trim() );
                      if ( seqNum.intValue() < 1 ) {
                          throw new IllegalArgumentException( "Not a positive integer" );
                      }
                  }
                  response.add( seqNum );
              }
              else {
                  // Simple sequence
  
                  // Add the first number in the range.
                  Integer firstNum = new Integer( rawSet.substring( 0, checkColon ) );
                  int first = firstNum.intValue();
                  if ( first < 1 ) {
                      throw new IllegalArgumentException( "Not a positive integer" );
                  }
                  response.add( firstNum );
  
                  Integer lastNum;
                  int last;
                  if ( rawSet.indexOf( "*" ) != -1 ) {
                      // Range from firstNum to '*'
                      // Add -1, to indicate unended range.
                      lastNum = new Integer( -1 );
                  }
                  else {
                      // Get the final num, and add all numbers in range.
                      lastNum = new Integer( rawSet.substring( checkColon + 1 ) );
                      last = lastNum.intValue();
                      if ( last < 1 ) {
                          throw new IllegalArgumentException( "Not a positive integer" );
                      }
                      if ( last < first ) {
                          throw new IllegalArgumentException( "Not an increasing range" );
                      }
  
                      for ( int i = (first + 1); i <= last; i++ ) {
                          response.add( new Integer( i ) );
                      }
                  }
              }
  
          }
          else {
              // Comma present, compound range.
              try {
                  String firstRawSet = rawSet.substring( 0, checkComma );
                  String secondRawSet = rawSet.substring( checkComma + 1 );
                  response.addAll( parseSet( firstRawSet ) );
                  response.addAll( parseSet( secondRawSet ) );
              }
              catch ( IllegalArgumentException e ) {
                  throw e;
              }
          }
          return response;
  
      }
  
      public String format()
      {
          return "<set>";
      }
  
  }
  
  
  
  1.2       +6 -0      jakarta-james/proposals/imap/test/org/apache/james/imapserver/Authenticate.test
  
  Index: Authenticate.test
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/test/org/apache/james/imapserver/Authenticate.test,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Authenticate.test	15 Jan 2002 08:38:27 -0000	1.1
  +++ Authenticate.test	23 Jan 2002 21:53:33 -0000	1.2
  @@ -1,2 +1,8 @@
   C: abcd AUTHENTICATE KERBEROS_V4
   S: abcd NO AUTHENTICATE Unsupported authentication mechanism
  +
  +C: abcd AUTHENTICATE
  +S: abcd BAD Missing argument <auth-type>: Command should be <tag> AUTHENTICATE <auth-type>
  +
  +C: abcd AUTHENTICATE KERBEROS_V4 extra
  +S: abcd BAD Extra token found: Command should be <tag> AUTHENTICATE <auth-type>
  
  
  
  1.2       +4 -1      jakarta-james/proposals/imap/test/org/apache/james/imapserver/Capability.test
  
  Index: Capability.test
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/test/org/apache/james/imapserver/Capability.test,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Capability.test	15 Jan 2002 08:38:27 -0000	1.1
  +++ Capability.test	23 Jan 2002 21:53:33 -0000	1.2
  @@ -1,3 +1,6 @@
   C: abcd CAPABILITY
   S: * CAPABILITY IMAP4rev1
  -S: abcd OK CAPABILITY completed
  \ No newline at end of file
  +S: abcd OK CAPABILITY completed
  +
  +C: abcd CAPABILITY extra stuff
  +S: abcd BAD Extra token found: Command should be <tag> CAPABILITY
  \ No newline at end of file
  
  
  
  1.2       +7 -0      jakarta-james/proposals/imap/test/org/apache/james/imapserver/IMAPTest.java
  
  Index: IMAPTest.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/test/org/apache/james/imapserver/IMAPTest.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- IMAPTest.java	15 Jan 2002 08:38:27 -0000	1.1
  +++ IMAPTest.java	23 Jan 2002 21:53:33 -0000	1.2
  @@ -1,3 +1,10 @@
  +/*
  + * Copyright (C) The Apache Software Foundation. All rights reserved.
  + *
  + * This software is published under the terms of the Apache Software License
  + * version 1.1, a copy of which has been included with this distribution in
  + * the LICENSE file.
  + */
   package org.apache.james.imapserver;
   
   import javax.mail.internet.InternetAddress;
  
  
  
  1.2       +7 -0      jakarta-james/proposals/imap/test/org/apache/james/imapserver/InitialMail.java
  
  Index: InitialMail.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/test/org/apache/james/imapserver/InitialMail.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- InitialMail.java	15 Jan 2002 08:38:27 -0000	1.1
  +++ InitialMail.java	23 Jan 2002 21:53:33 -0000	1.2
  @@ -1,3 +1,10 @@
  +/*
  + * Copyright (C) The Apache Software Foundation. All rights reserved.
  + *
  + * This software is published under the terms of the Apache Software License
  + * version 1.1, a copy of which has been included with this distribution in
  + * the LICENSE file.
  + */
   package org.apache.james.imapserver;
   
   import junit.framework.TestCase;
  
  
  
  1.2       +7 -0      jakarta-james/proposals/imap/test/org/apache/james/imapserver/InitialUsers.java
  
  Index: InitialUsers.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/test/org/apache/james/imapserver/InitialUsers.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- InitialUsers.java	15 Jan 2002 08:38:27 -0000	1.1
  +++ InitialUsers.java	23 Jan 2002 21:53:33 -0000	1.2
  @@ -1,3 +1,10 @@
  +/*
  + * Copyright (C) The Apache Software Foundation. All rights reserved.
  + *
  + * This software is published under the terms of the Apache Software License
  + * version 1.1, a copy of which has been included with this distribution in
  + * the LICENSE file.
  + */
   package org.apache.james.imapserver;
   
   import junit.framework.Test;
  
  
  
  1.2       +18 -1     jakarta-james/proposals/imap/test/org/apache/james/imapserver/Login.test
  
  Index: Login.test
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/test/org/apache/james/imapserver/Login.test,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Login.test	15 Jan 2002 08:38:27 -0000	1.1
  +++ Login.test	23 Jan 2002 21:53:33 -0000	1.2
  @@ -1 +1,18 @@
  -// Empty file to use for simple login test.
  \ No newline at end of file
  +// Empty file to use for simple login test.
  +C: a001 LOGIN
  +S: a001 BAD Missing argument <username>: Command should be <tag> LOGIN <username> <password>
  +
  +C: a002 LOGIN invaliduser
  +S: a002 BAD Missing argument <password>: Command should be <tag> LOGIN <username> <password>
  +
  +C: a002a LOGIN imapuser password extra
  +S: a002a BAD Extra token found: Command should be <tag> LOGIN <username> <password>
  +
  +C: a003 LOGIN invaliduser password
  +S: a003 NO LOGIN failed
  +
  +C: a004 LOGIN imapuser invalid
  +S: a004 NO LOGIN failed
  +
  +C: a005 LOGIN imapuser password
  +S: a005 OK LOGIN completed
  \ No newline at end of file
  
  
  
  1.2       +3 -0      jakarta-james/proposals/imap/test/org/apache/james/imapserver/Logout.test
  
  Index: Logout.test
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/test/org/apache/james/imapserver/Logout.test,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Logout.test	15 Jan 2002 08:38:27 -0000	1.1
  +++ Logout.test	23 Jan 2002 21:53:33 -0000	1.2
  @@ -1,3 +1,6 @@
  +C: a023 LOGOUT extra stuff
  +S: a023 BAD Extra token found: Command should be <tag> LOGOUT
  +
   C: A023 LOGOUT
   S: * BYE Server logging out
   S: A023 OK LOGOUT completed
  
  
  
  1.2       +7 -0      jakarta-james/proposals/imap/test/org/apache/james/imapserver/TestAuthenticated.java
  
  Index: TestAuthenticated.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/test/org/apache/james/imapserver/TestAuthenticated.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TestAuthenticated.java	15 Jan 2002 08:38:27 -0000	1.1
  +++ TestAuthenticated.java	23 Jan 2002 21:53:33 -0000	1.2
  @@ -1,3 +1,10 @@
  +/*
  + * Copyright (C) The Apache Software Foundation. All rights reserved.
  + *
  + * This software is published under the terms of the Apache Software License
  + * version 1.1, a copy of which has been included with this distribution in
  + * the LICENSE file.
  + */
   package org.apache.james.imapserver;
   
   import junit.framework.TestCase;
  
  
  
  1.2       +8 -1      jakarta-james/proposals/imap/test/org/apache/james/imapserver/TestNonAuthenticated.java
  
  Index: TestNonAuthenticated.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/test/org/apache/james/imapserver/TestNonAuthenticated.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TestNonAuthenticated.java	15 Jan 2002 08:38:27 -0000	1.1
  +++ TestNonAuthenticated.java	23 Jan 2002 21:53:33 -0000	1.2
  @@ -1,3 +1,10 @@
  +/*
  + * Copyright (C) The Apache Software Foundation. All rights reserved.
  + *
  + * This software is published under the terms of the Apache Software License
  + * version 1.1, a copy of which has been included with this distribution in
  + * the LICENSE file.
  + */
   package org.apache.james.imapserver;
   
   import junit.framework.TestCase;
  @@ -35,7 +42,7 @@
           TestSuite suite = new TestSuite();
           suite.addTest( new TestNonAuthenticated( "Capability" ) );
           suite.addTest( new TestNonAuthenticated( "Authenticate" ) );
  -        suite.addTest( new TestAuthenticated( "Login" ) );
  +        suite.addTest( new TestNonAuthenticated( "Login" ) );
           suite.addTest( new TestNonAuthenticated( "Logout" ) );
   
           return suite;
  
  
  
  1.2       +7 -0      jakarta-james/proposals/imap/test/org/apache/james/imapserver/TestSelected.java
  
  Index: TestSelected.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/proposals/imap/test/org/apache/james/imapserver/TestSelected.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TestSelected.java	15 Jan 2002 08:38:27 -0000	1.1
  +++ TestSelected.java	23 Jan 2002 21:53:33 -0000	1.2
  @@ -1,3 +1,10 @@
  +/*
  + * Copyright (C) The Apache Software Foundation. All rights reserved.
  + *
  + * This software is published under the terms of the Apache Software License
  + * version 1.1, a copy of which has been included with this distribution in
  + * the LICENSE file.
  + */
   package org.apache.james.imapserver;
   
   import junit.framework.Test;
  
  
  
  1.1                  jakarta-james/proposals/imap/test/org/apache/james/imapserver/commands/ArgumentTest.java
  
  Index: ArgumentTest.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.imapserver.commands;
  
  import junit.framework.TestCase;
  
  import java.util.StringTokenizer;
  
  public final class ArgumentTest
          extends TestCase
  {
      public ArgumentTest( String s )
      {
          super( s );
      }
  
      public void testAstring() throws Exception
      {
          AstringArgument arg = new AstringArgument( "test" );
          ParseChecker parser = new ParseChecker( arg );
  
          parser.check( "straightup", "straightup" );
          parser.check( "quoted", "\"quoted\"" );
          parser.check( "with space", "\"with space\"" );
  
          // Test currently fails - don't see whitespace.
          //parser.check( "multiple   spaces", "\"multiple   spaces\"" );
  
          parser.checkFail( "Missing argument <test>", "" );
          parser.checkFail( "Missing closing quote for <test>", "\"something" );
          parser.checkFail( "Missing closing quote for <test>", "\"" );
          parser.checkFail( "Missing closing quote for <test>", "\"something special" );
      }
  
      private static class ParseChecker
      {
          private ImapArgument arg;
  
          ParseChecker( ImapArgument arg )
          {
              this.arg = arg;
          }
  
          public void check( Object expected, String input )
          {
              StringTokenizer tokens = new StringTokenizer( input );
              Object result = null;
              try {
                  result = this.arg.parse( tokens );
              }
              catch ( Exception e ) {
                  fail( "Error encountered: " + e.getMessage() );
              }
  
              assertEquals( expected, result );
          }
  
          public void checkFail( String expectedError, String input )
          {
              StringTokenizer tokens = new StringTokenizer( input );
              try {
                  Object result = this.arg.parse( tokens );
              }
              catch ( Exception e ) {
                  assertEquals( expectedError, e.getMessage() );
                  return;
              }
  
              fail( "Expected error" );
          }
      }
  }
  
  
  
  1.1                  jakarta-james/proposals/imap/test/org/apache/james/test/JamesTask.java
  
  Index: JamesTask.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.test;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.AntClassLoader;
  import org.apache.tools.ant.types.Path;
  import org.apache.tools.ant.types.Reference;
  import org.apache.tools.ant.types.CommandlineJava;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.framework.parameters.Parameterizable;
  import org.apache.avalon.framework.ExceptionUtil;
  import org.apache.avalon.framework.CascadingRuntimeException;
  import org.apache.avalon.phoenix.components.embeddor.SingleAppEmbeddor;
  
  /**
   * An attempt at a task which can launch James from Ant, and shut it down again.
   * Doesn't really work, yet.
   */
  public final class JamesTask
         extends org.apache.tools.ant.Task
  {
      private CommandlineJava cmdl = new CommandlineJava();
      private Parameters m_parameters;
      private static SingleAppEmbeddor m_embeddor;
      private String m_action;
  
      public void setAction( String action )
      {
          m_action = action;
      }
  
      /**
       * Set the classpath to be used for this compilation.
       */
      public void setClasspath(Path s) {
          createClasspath().append(s);
      }
  
      /**
       * Creates a nested classpath element
       */
      public Path createClasspath() {
          return cmdl.createClasspath(project).createPath();
      }
  
      /**
       * Adds a reference to a CLASSPATH defined elsewhere.
       */
      public void setClasspathRef(Reference r) {
          createClasspath().setRefid(r);
      }
  
  
      public void execute() throws BuildException
      {
          if ( m_action.equalsIgnoreCase( "start" ) ) {
              startup();
          }
          else if ( m_action.equalsIgnoreCase( "stop" ) ) {
              shutdown();
          }
          else if ( m_action.equalsIgnoreCase( "start-stop" ) ) {
              startup();
              shutdown();
          }
          else if ( m_action.equalsIgnoreCase( "restart" ) ) {
              optionalShutdown();
              startup();
          }
          else {
              throw new BuildException( "Invalid action: '" + m_action + "'" );
          }
      }
  
      private void startup() throws BuildException
      {
          if ( m_embeddor != null ) {
             throw new BuildException( "Already started" );
          }
  
          m_parameters = new Parameters();
  //        m_parameters.setParameter( "log-destination", "." );
  //        m_parameters.setParameter( "log-priority", "DEBUG" );
  //        m_parameters.setParameter( "application-name", "james" );
          m_parameters.setParameter( "application-location", "dist/apps/james.sar");
  
          try
          {
              m_embeddor = new SingleAppEmbeddor();
              if( m_embeddor instanceof Parameterizable )
              {
                  ( (Parameterizable)m_embeddor ).parameterize( m_parameters );
              }
              m_embeddor.initialize();
  
  //            final Thread thread = new Thread( this, "Phoenix" );
  //            thread.start();
          }
          catch( final Throwable throwable )
          {
              System.out.println( "Exception in initiliaze()" );
              throw new BuildException( throwable );
          }
  
          try
          {
              ClassLoader ctxLoader = Thread.currentThread().getContextClassLoader();
              AntClassLoader loader = new AntClassLoader(ctxLoader, project, cmdl.getClasspath(), true);
              loader.setIsolated(false);
              loader.setThreadContextLoader();
              // nothing
              // m_embeddor.execute();
              // Launch the startup thread.
              Thread startThread = new StartupThread();
              startThread.start();
  
              // Hack to make sure that the embeddor has actually started.
              // Need to make a change to Phoenix, so that we can wait til it's running.
              // Yeild processor.
              Thread.sleep( 1000 );
              // m_embeddor will now be in use until applications are deployed.
              synchronized ( m_embeddor ) {
                  System.out.println( "got synch at: " + System.currentTimeMillis() );
              }
          }
          catch( final Throwable throwable )
          {
              System.out.println( "Exception in execute()" );
              throw new BuildException( throwable );
          }
  
      }
  
      private class StartupThread extends Thread
      {
          StartupThread()
          {
              super( "JamesStartup" );
              this.setDaemon( true );
          }
  
          public void run()
          {
              try {
                  m_embeddor.execute();
              }
              catch ( Exception exc ) {
                  exc.printStackTrace();
                  throw new CascadingRuntimeException( "Exception in execute()", exc );
              }
          }
  
      }
  
      private void optionalShutdown() throws BuildException
      {
          if ( m_embeddor != null ) {
              shutdown();
          }
      }
  
      private void shutdown() throws BuildException
      {
          System.out.println( "In shutdown()" );
          if ( m_embeddor == null ) {
              throw new BuildException( "Not running." );
          }
  
          try
          {
              m_embeddor.dispose();
              System.out.println( "Called dispose()" );
              m_embeddor = null;
              m_parameters = null;
          }
          catch( final Throwable throwable )
          {
              System.out.println( "Exception in dispose()" );
              throw new BuildException( throwable );
          }
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>