pgoldstein    2003/03/25 22:31:17

  Modified:    .        Tag: branch_2_1_fcs build.xml
               src/java/org/apache/james/core Tag: branch_2_1_fcs
                        MailHeaders.java
               src/java/org/apache/james/smtpserver Tag: branch_2_1_fcs
                        SMTPHandler.java
               src/java/org/apache/james/nntpserver Tag: branch_2_1_fcs
                        NNTPHandler.java
               src/java/org/apache/james/nntpserver/repository Tag:
                        branch_2_1_fcs NNTPArticle.java
                        NNTPArticleImpl.java NNTPRepository.java
                        NNTPRepositoryImpl.java
  Added:       src/java/org/apache/james/util Tag: branch_2_1_fcs
                        DotStuffingInputStream.java
  Removed:     src/java/org/apache/james/smtpserver Tag: branch_2_1_fcs
                        SMTPInputStream.java
               src/java/org/apache/james/nntpserver/repository Tag:
                        branch_2_1_fcs NNTPLineReader.java
                        NNTPLineReaderImpl.java
  Log:
  Committing NNTP changes to resolve encoding issue.
  Changes do not check incoming header for character
  set, but instead treat the article as a raw block of
  bytes.  Checked in for Noel Bergman.
  
  Revision  Changes    Path
  No                   revision
  
  
  No                   revision
  
  
  1.116.2.5 +2 -2      jakarta-james/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-james/build.xml,v
  retrieving revision 1.116.2.4
  retrieving revision 1.116.2.5
  diff -u -r1.116.2.4 -r1.116.2.5
  --- build.xml 11 Mar 2003 01:35:16 -0000      1.116.2.4
  +++ build.xml 26 Mar 2003 06:31:16 -0000      1.116.2.5
  @@ -21,7 +21,7 @@
       <property file="${user.home}/.ant.properties"/>
       <property name="name" value="james"/>
       <property name="Name" value="James"/>
  -    <property name="version" value="2.1.3a1"/>
  +    <property name="version" value="2.1.3a2"/>
       <property name="year" value="1999-2003"/>
       <!-- There should be no need to override default compiler but need to change
       javac task to run without this -->
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.4.4.3   +12 -18    jakarta-james/src/java/org/apache/james/core/MailHeaders.java
  
  Index: MailHeaders.java
  ===================================================================
  RCS file: /home/cvs/jakarta-james/src/java/org/apache/james/core/MailHeaders.java,v
  retrieving revision 1.4.4.2
  retrieving revision 1.4.4.3
  diff -u -r1.4.4.2 -r1.4.4.3
  --- MailHeaders.java  8 Mar 2003 21:54:03 -0000       1.4.4.2
  +++ MailHeaders.java  26 Mar 2003 06:31:16 -0000      1.4.4.3
  @@ -95,30 +95,24 @@
           super(in);
       }
   
  -// TODO: Overloading error.  This is extremely dangerous, as the overloaded call
  -//       does not behave like an overridden call.  Specifically, the choice of
  -//       which method to invoke is made at compile time, not at runtime.
  -//       Potentially very, very bad if the behaviors diverge.
  -
       /**
  -     * Write the headers to an PrintStream
  +     * Write the headers to an output stream
        *
        * @param writer the stream to which to write the headers
        */
  -    public void writeTo(PrintStream writer) {
  +    public void writeTo(OutputStream out) {
  +        PrintStream pout;
  +        if (out instanceof PrintStream) {
  +            pout = (PrintStream)out;
  +        } else {
  +            pout = new PrintStream(out);
  +        }
           for (Enumeration e = super.getAllHeaderLines(); e.hasMoreElements(); ) {
  -            writer.println((String) e.nextElement());
  +            pout.print((String) e.nextElement());
  +            pout.print("\r\n");
           }
  -        writer.println("");
  -    }
  -
  -    /**
  -     * Write the headers to an output stream
  -     *
  -     * @param out the stream to which to write the headers
  -     */
  -    public void writeTo(OutputStream out) {
  -        writeTo(new PrintStream(out));
  +        // Print trailing CRLF
  +        pout.print("\r\n");
       }
   
       /**
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.1.2.1   +86 -0     
jakarta-james/src/java/org/apache/james/util/Attic/DotStuffingInputStream.java
  
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.35.4.9  +2 -2      
jakarta-james/src/java/org/apache/james/smtpserver/SMTPHandler.java
  
  Index: SMTPHandler.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-james/src/java/org/apache/james/smtpserver/SMTPHandler.java,v
  retrieving revision 1.35.4.8
  retrieving revision 1.35.4.9
  diff -u -r1.35.4.8 -r1.35.4.9
  --- SMTPHandler.java  8 Mar 2003 21:54:07 -0000       1.35.4.8
  +++ SMTPHandler.java  26 Mar 2003 06:31:16 -0000      1.35.4.9
  @@ -1246,7 +1246,7 @@
                       msgIn = new SizeLimitedInputStream(msgIn, maxMessageSize);
                   }
                   // Removes the dot stuffing
  -                msgIn = new SMTPInputStream(msgIn);
  +                msgIn = new DotStuffingInputStream(msgIn);
                   // Parse out the message headers
                   MailHeaders headers = new MailHeaders(msgIn);
                   headers = processMailHeaders(headers);
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.25.4.9  +185 -43   
jakarta-james/src/java/org/apache/james/nntpserver/NNTPHandler.java
  
  Index: NNTPHandler.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-james/src/java/org/apache/james/nntpserver/NNTPHandler.java,v
  retrieving revision 1.25.4.8
  retrieving revision 1.25.4.9
  diff -u -r1.25.4.8 -r1.25.4.9
  --- NNTPHandler.java  8 Mar 2003 21:54:04 -0000       1.25.4.8
  +++ NNTPHandler.java  26 Mar 2003 06:31:17 -0000      1.25.4.9
  @@ -61,20 +61,20 @@
   import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
   import org.apache.avalon.excalibur.pool.Poolable;
   import org.apache.avalon.framework.activity.Disposable;
  -import org.apache.avalon.framework.component.ComponentException;
  -import org.apache.avalon.framework.component.ComponentManager;
  -import org.apache.avalon.framework.component.Composable;
   import org.apache.avalon.framework.configuration.Configurable;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.ConfigurationException;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
   import org.apache.avalon.framework.logger.Logger;
  +import org.apache.james.core.MailHeaders;
   import org.apache.james.nntpserver.repository.NNTPArticle;
   import org.apache.james.nntpserver.repository.NNTPGroup;
  -import org.apache.james.nntpserver.repository.NNTPLineReaderImpl;
   import org.apache.james.nntpserver.repository.NNTPRepository;
   import org.apache.james.services.UsersRepository;
   import org.apache.james.services.UsersStore;
  +import org.apache.james.util.CharTerminatedInputStream;
  +import org.apache.james.util.DotStuffingInputStream;
  +import org.apache.james.util.ExtraDotOutputStream;
   import org.apache.james.util.InternetPrintWriter;
   import org.apache.james.util.RFC977DateFormat;
   import org.apache.james.util.RFC2980DateFormat;
  @@ -82,16 +82,29 @@
   import org.apache.james.util.watchdog.Watchdog;
   import org.apache.james.util.watchdog.WatchdogTarget;
   
  +import java.io.BufferedInputStream;
  +import java.io.BufferedOutputStream;
   import java.io.BufferedReader;
   import java.io.BufferedWriter;
  +import java.io.ByteArrayInputStream;
   import java.io.IOException;
  +import java.io.InputStream;
   import java.io.InputStreamReader;
  +import java.io.OutputStream;
   import java.io.OutputStreamWriter;
   import java.io.PrintWriter;
  +import java.io.SequenceInputStream;
   import java.net.Socket;
   import java.text.DateFormat;
   import java.text.ParseException;
  -import java.util.*;
  +import java.util.ArrayList;
  +import java.util.Calendar;
  +import java.util.Date;
  +import java.util.Iterator;
  +import java.util.List;
  +import java.util.Locale;
  +import java.util.StringTokenizer;
  +import javax.mail.MessagingException;
   
   /**
    * The NNTP protocol is defined by RFC 977.
  @@ -99,7 +112,6 @@
    * URL: http://www.ietf.org/internet-drafts/draft-ietf-nntpext-base-15.txt
    *
    * Common NNTP extensions are in RFC 2980.
  - *
    */
   public class NNTPHandler
       extends AbstractLogEnabled
  @@ -181,6 +193,11 @@
       private final static String COMMAND_QUIT = "QUIT";
   
       /**
  +     * The text string for the NNTP SLAVE command.
  +     */
  +    private final static String COMMAND_SLAVE = "SLAVE";
  +
  +    /**
        * The text string for the NNTP DATE command.
        */
       private final static String COMMAND_DATE = "DATE";
  @@ -231,6 +248,11 @@
       private final static String COMMAND_AUTHINFO = "AUTHINFO";
   
       /**
  +     * The text string for the NNTP PAT command.
  +     */
  +    private final static String COMMAND_PAT = "PAT";
  +
  +    /**
        * The text string for the NNTP MODE READER parameter.
        */
       private final static String MODE_TYPE_READER = "READER";
  @@ -251,22 +273,47 @@
       private final static String AUTHINFO_PARAM_PASS = "PASS";
   
       /**
  +     * The character array that indicates termination of an NNTP message
  +     */
  +    private final static char[] NNTPTerminator = { '\r', '\n', '.', '\r', '\n' };
  +
  +    /**
        * The thread executing this handler 
        */
       private Thread handlerThread;
   
       /**
  +     * The remote host name obtained by lookup on the socket.
  +     */
  +    private String remoteHost;
  +
  +    /**
  +     * The remote IP address of the socket.
  +     */
  +    private String remoteIP;
  +
  +    /**
        * The TCP/IP socket over which the POP3 interaction
        * is occurring
        */
       private Socket socket;
   
       /**
  +     * The incoming stream of bytes coming from the socket.
  +     */
  +    private InputStream in;
  +
  +    /**
        * The reader associated with incoming characters.
        */
       private BufferedReader reader;
   
       /**
  +     * The socket's output stream
  +     */
  +    private OutputStream outs;
  +
  +    /**
        * The writer to which outgoing messages are written.
        */
       private PrintWriter writer;
  @@ -371,16 +418,31 @@
        * @see 
org.apache.avalon.cornerstone.services.connection.ConnectionHandler#handleConnection(Socket)
        */
       public void handleConnection( Socket connection ) throws IOException {
  -
           try {
               this.socket = connection;
               synchronized (this) {
                   handlerThread = Thread.currentThread();
               }
  -            reader = new BufferedReader(new 
InputStreamReader(socket.getInputStream(), "ASCII"), 1024);
  -            writer = new InternetPrintWriter(new BufferedWriter(new 
OutputStreamWriter(socket.getOutputStream()), 1024), true);
  +            remoteIP = socket.getInetAddress().getHostAddress();
  +            remoteHost = socket.getInetAddress().getHostName();
  +            in = new BufferedInputStream(socket.getInputStream(), 1024);
  +            // An ASCII encoding can be used because all transmissions other
  +            // that those in the message body command are guaranteed
  +            // to be ASCII
  +            reader = new BufferedReader(new InputStreamReader(in, "ASCII"), 512);
  +            outs = new BufferedOutputStream(socket.getOutputStream(), 1024);
  +            writer = new InternetPrintWriter(outs, true);
           } catch (Exception e) {
  -            getLogger().error( "Cannot open connection from: " + e.getMessage(), e 
);
  +            StringBuffer exceptionBuffer = 
  +                new StringBuffer(256)
  +                    .append("Cannot open connection from ")
  +                    .append(remoteHost)
  +                    .append(" (")
  +                    .append(remoteIP)
  +                    .append("): ")
  +                    .append(e.getMessage());
  +            String exceptionString = exceptionBuffer.toString();
  +            getLogger().error(exceptionString, e );
           }
   
           try {
  @@ -407,17 +469,16 @@
               }
               theWatchdog.stop();
   
  -            getLogger().debug("Connection closed");
  +            getLogger().info("Connection closed");
           } catch (Exception e) {
  -            // if the connection has been idled out, the
  +            // If the connection has been idled out, the
               // socket will be closed and null.  Do NOT
               // log the exception or attempt to send the
               // closing connection message
               if (socket != null) {
                   try {
                       doQUIT(null);
  -                } catch(Throwable t) { }
  -
  +                } catch (Throwable t) {}
                   getLogger().error( "Exception during connection:" + e.getMessage(), 
e );
               }
           } finally {
  @@ -449,11 +510,16 @@
               reader = null;
           }
   
  +        in = null;
  +
           if (writer != null) {
               writer.close();
               writer = null;
           }
  +        outs = null;
   
  +        remoteHost = null;
  +        remoteIP = null;
           try {
               if (socket != null) {
                   socket.close();
  @@ -510,14 +576,20 @@
           }
           command = command.toUpperCase(Locale.US);
   
  +        boolean returnValue = true;
           if (!isAuthorized(command) ) {
               writeLoggedFlushedResponse("502 User is not authenticated");
               getLogger().debug("Command not allowed.");
  -            return true;
  +            return returnValue;
           }
  -        if ((command.equals(COMMAND_MODE)) && (argument != null) &&
  -            argument.toUpperCase(Locale.US).equals(MODE_TYPE_READER)) {
  -            doMODEREADER(argument);
  +        if ((command.equals(COMMAND_MODE)) && (argument != null)) {
  +            if (argument.toUpperCase(Locale.US).equals(MODE_TYPE_READER)) {
  +                doMODEREADER(argument);
  +            } else if (argument.toUpperCase(Locale.US).equals(MODE_TYPE_STREAM)) {
  +                doMODESTREAM(argument);
  +            } else {
  +                writeLoggedFlushedResponse("500 Command not understood");
  +            }
           } else if ( command.equals(COMMAND_LIST)) {
               doLIST(argument);
           } else if ( command.equals(COMMAND_GROUP) ) {
  @@ -540,6 +612,7 @@
               doIHAVE(argument);
           } else if ( command.equals(COMMAND_QUIT) ) {
               doQUIT(argument);
  +            returnValue = false;
           } else if ( command.equals(COMMAND_DATE) ) {
               doDATE(argument);
           } else if ( command.equals(COMMAND_HELP) ) {
  @@ -560,12 +633,14 @@
               doXHDR(argument);
           } else if ( command.equals(COMMAND_AUTHINFO) ) {
               doAUTHINFO(argument);
  -        } else if ( command.equals("PAT") ) {
  +        } else if ( command.equals(COMMAND_SLAVE) ) {
  +            doSLAVE(argument);
  +        } else if ( command.equals(COMMAND_PAT) ) {
               doPAT(argument);
           } else {
               doUnknownCommand(command, argument);
           }
  -        return (command.equals(COMMAND_QUIT) == false);
  +        return returnValue;
       }
   
       /**
  @@ -608,9 +683,7 @@
               writeLoggedFlushedResponse("501 Syntax error");
               return;
           }
  -
           command = command.toUpperCase(Locale.US);
  -
           if ( command.equals(AUTHINFO_PARAM_USER) ) {
               // Reject re-authentication
               if ( isAlreadyAuthenticated ) {
  @@ -661,12 +734,13 @@
        * an argument.
        *
        * @param argument the argument passed in with the NEWNEWS command.
  -     *                 Should be NEWNEWS newsgroups date time [GMT] [<distribution>]
  -     *                 see RFC 977 #3.8, RFC 2980 #4.5.
  +     *                 Should be a wildmat followed by a date.
        */
       private void doNEWNEWS(String argument) {
  +        // see section 11.4
   
           String wildmat = "*";
  +
           if (argument != null) {
               int spaceIndex = argument.indexOf(" ");
               if (spaceIndex >= 0) {
  @@ -693,16 +767,13 @@
           }
   
           writeLoggedFlushedResponse("230 list of new articles by message-id 
follows");
  -
  -        Iterator groups = 
theConfigData.getNNTPRepository().getMatchedGroups(wildmat);
  -        while (groups.hasNext() ) {
  -            Iterator articles = 
((NNTPGroup)(groups.next())).getArticlesSince(theDate);
  -            while ( articles.hasNext() ) {
  +        Iterator groupIter = 
theConfigData.getNNTPRepository().getMatchedGroups(wildmat);
  +        while ( groupIter.hasNext() ) {
  +            Iterator articleIter = 
((NNTPGroup)(groupIter.next())).getArticlesSince(theDate);
  +            while (articleIter.hasNext()) {
                   StringBuffer iterBuffer =
  -                                         new StringBuffer(64)
  -                                         .append("<")
  -                                         
.append(((NNTPArticle)articles.next()).getUniqueID())
  -                                         .append(">");
  +                    new StringBuffer(64)
  +                        .append(((NNTPArticle)articleIter.next()).getUniqueID());
                   writeLoggedResponse(iterBuffer.toString());
               }
           }
  @@ -713,7 +784,7 @@
        * Lists the groups added since the date passed in as
        * an argument.
        *
  -     * @param argument the argument passed in with the NEWNEWS command.
  +     * @param argument the argument passed in with the NEWGROUPS command.
        *                 Should be a date.
        */
       private void doNEWGROUPS(String argument) {
  @@ -763,6 +834,16 @@
       }
   
       /**
  +     * Acknowledges a SLAVE command.  No special preference is given
  +     * to slave connections.
  +     *
  +     * @param argument the argument passed in with the SLAVE command.
  +     */
  +    private void doSLAVE(String argument) {
  +        writeLoggedFlushedResponse("202 slave status noted");
  +    }
  +
  +    /**
        * Returns the current date according to the news server.
        *
        * @param argument the argument passed in with the DATE command
  @@ -770,7 +851,7 @@
       private void doDATE(String argument) {
           Date dt = new Date(System.currentTimeMillis()-UTC_OFFSET);
           String dtStr = DF_RFC2980.format(new Date(dt.getTime() - UTC_OFFSET));
  -        writeLoggedFlushedResponse("111 "+dtStr);
  +        writeLoggedFlushedResponse("111 " + dtStr);
       }
   
       /**
  @@ -788,7 +869,6 @@
        * @param argument the argument passed in with the LIST command.
        */
       private void doLIST(String argument) {
  -
           // see section 9.4.1
           String wildmat = "*";
           boolean isListNewsgroups = false;
  @@ -862,7 +942,12 @@
               writeLoggedFlushedResponse("435 article not wanted - do not send it");
           } else {
               writeLoggedFlushedResponse("335 send article to be transferred. End 
with <CR-LF>.<CR-LF>");
  -            createArticle();
  +            try {
  +                createArticle();
  +            } catch (RuntimeException e) {
  +                writeLoggedFlushedResponse("436 transfer failed - try again later");
  +                throw e;
  +            }
               writeLoggedFlushedResponse("235 article received ok");
           }
       }
  @@ -1007,7 +1092,8 @@
               }
           }
           if (article != null) {
  -            article.writeBody(writer);
  +            writer.flush();
  +            article.writeBody(new ExtraDotOutputStream(outs));
               writeLoggedFlushedResponse(".");
           }
       }
  @@ -1074,7 +1160,8 @@
               }
           }
           if (article != null) {
  -            article.writeHead(writer);
  +            writer.flush();
  +            article.writeHead(new ExtraDotOutputStream(outs));
               writeLoggedFlushedResponse(".");
           }
       }
  @@ -1141,7 +1228,8 @@
               }
           }
           if (article != null) {
  -            article.writeArticle(writer);
  +            writer.flush();
  +            article.writeArticle(new ExtraDotOutputStream(outs));
               writeLoggedFlushedResponse(".");
           }
       }
  @@ -1278,6 +1366,16 @@
       }
   
       /**
  +     * Informs the server that the client is a news server.
  +     *
  +     * @param argument the argument passed in with the MODE STREAM command
  +     */
  +    private void doMODESTREAM(String argument) {
  +        // 7.2
  +        writeLoggedFlushedResponse("500 Command not understood");
  +    }
  +
  +    /**
        * Gets a listing of article numbers in specified group name
        * or in the already selected group if the groupName is null.
        *
  @@ -1436,9 +1534,9 @@
           } else {
               writeLoggedResponse("224 Overview information follows");
               for ( int i = 0 ; i < article.length ; i++ ) {
  -                article[i].writeOverview(writer);
  +                article[i].writeOverview(outs);
                   if (i % 100 == 0) {
  -                    // Reset the watchdog ever hundred headers or so
  +                    // Reset the watchdog every hundred headers or so
                       // to ensure the connection doesn't timeout for slow
                       // clients
                       theWatchdog.reset();
  @@ -1452,7 +1550,51 @@
        * Handles the transaction for getting the article data.
        */
       private void createArticle() {
  -        theConfigData.getNNTPRepository().createArticle(new 
NNTPLineReaderImpl(reader));
  +        try {
  +            InputStream msgIn = new CharTerminatedInputStream(in, NNTPTerminator);
  +            // Removes the dot stuffing
  +            msgIn = new DotStuffingInputStream(msgIn);
  +            MailHeaders headers = new MailHeaders(msgIn);
  +            processMessageHeaders(headers);
  +            processMessage(headers, msgIn);
  +        } catch (MessagingException me) {
  +            throw new NNTPException("MessagingException encountered when loading 
article.");
  +        }
  +    }
  +
  +    /**
  +     * Processes the NNTP message headers coming in off the wire.
  +     *
  +     * @param headers the headers of the message being read
  +     */
  +    private MailHeaders processMessageHeaders(MailHeaders headers)
  +        throws MessagingException {
  +        return headers;
  +    }
  +
  +    /**
  +     * Processes the NNTP message coming in off the wire.  Reads the
  +     * content and delivers to the spool.
  +     *
  +     * @param headers the headers of the message being read
  +     * @param msgIn the stream containing the message content
  +     */
  +    private void processMessage(MailHeaders headers, InputStream bodyIn)
  +        throws MessagingException {
  +        InputStream messageIn = null;
  +        try {
  +            messageIn = new SequenceInputStream(new 
ByteArrayInputStream(headers.toByteArray()), bodyIn);
  +            theConfigData.getNNTPRepository().createArticle(messageIn);
  +        } finally {
  +            if (messageIn != null) {
  +                try {
  +                    messageIn.close();
  +                } catch (IOException ioe) {
  +                    // Ignore exception on close.
  +                }
  +                messageIn = null;
  +            }
  +        }
       }
   
       /**
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.3.4.3   +9 -11     
jakarta-james/src/java/org/apache/james/nntpserver/repository/NNTPArticle.java
  
  Index: NNTPArticle.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-james/src/java/org/apache/james/nntpserver/repository/NNTPArticle.java,v
  retrieving revision 1.3.4.2
  retrieving revision 1.3.4.3
  diff -u -r1.3.4.2 -r1.3.4.3
  --- NNTPArticle.java  8 Mar 2003 21:54:05 -0000       1.3.4.2
  +++ NNTPArticle.java  26 Mar 2003 06:31:17 -0000      1.3.4.3
  @@ -58,12 +58,10 @@
   
   package org.apache.james.nntpserver.repository;
   
  -import java.io.PrintWriter;
  +import java.io.OutputStream;
   
   /** 
    * Contract exposed by a NewsGroup Article
  - *
  - * @author Harmeet Bedi <[EMAIL PROTECTED]>
    */
   public interface NNTPArticle {
   
  @@ -91,30 +89,30 @@
       /**
        * Writes the whole article to a writer.
        *
  -     * @param wrt the PrintWriter to which the article is written.
  +     * @param wrt the OutputStream to which the article is written.
        */
  -    void writeArticle(PrintWriter wrt);
  +    void writeArticle(OutputStream wrt);
   
       /**
        * Writes the article headers to a writer.
        *
  -     * @param wrt the PrintWriter to which the article is written.
  +     * @param wrt the OutputStream to which the article is written.
        */
  -    void writeHead(PrintWriter wrt);
  +    void writeHead(OutputStream wrt);
   
       /**
        * Writes the article body to a writer.
        *
  -     * @param wrt the PrintWriter to which the article is written.
  +     * @param wrt the OutputStream to which the article is written.
        */
  -    void writeBody(PrintWriter wrt);
  +    void writeBody(OutputStream wrt);
   
       /**
        * Writes the article overview to a writer.
        *
  -     * @param wrt the PrintWriter to which the article is written.
  +     * @param wrt the OutputStream to which the article is written.
        */
  -    void writeOverview(PrintWriter wrt);
  +    void writeOverview(OutputStream wrt);
   
       /**
        * Gets the header with the specified headerName.  Returns null
  
  
  
  1.10.4.6  +82 -60    
jakarta-james/src/java/org/apache/james/nntpserver/repository/NNTPArticleImpl.java
  
  Index: NNTPArticleImpl.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-james/src/java/org/apache/james/nntpserver/repository/NNTPArticleImpl.java,v
  retrieving revision 1.10.4.5
  retrieving revision 1.10.4.6
  diff -u -r1.10.4.5 -r1.10.4.6
  --- NNTPArticleImpl.java      8 Mar 2003 21:54:05 -0000       1.10.4.5
  +++ NNTPArticleImpl.java      26 Mar 2003 06:31:17 -0000      1.10.4.6
  @@ -58,22 +58,20 @@
   
   package org.apache.james.nntpserver.repository;
   
  +import org.apache.james.core.MailHeaders;
   import org.apache.james.nntpserver.NNTPException;
   import org.apache.avalon.excalibur.io.IOUtil;
   
   import javax.mail.internet.InternetHeaders;
  -
   import java.io.BufferedReader;
   import java.io.File;
   import java.io.FileInputStream;
   import java.io.FileReader;
   import java.io.IOException;
  -import java.io.PrintWriter;
  -
  +import java.io.OutputStream;
   
  -/**
  +/** 
    * Please see NNTPArticle for comments
  - *
    */
   class NNTPArticleImpl implements NNTPArticle {
   
  @@ -121,88 +119,101 @@
               fin = new FileInputStream(articleFile);
               InternetHeaders headers = new InternetHeaders(fin);
               String[] idheader = headers.getHeader("Message-Id");
  +            fin.close();
               return ( idheader.length > 0 ) ? idheader[0] : null;
  -        } catch(Exception ex) { 
  -            throw new NNTPException(ex); 
  +        } catch(Exception ex) {
  +            throw new NNTPException(ex);
           } finally {
               IOUtil.shutdownStream(fin);
           }
       }
   
       /**
  -     * @see 
org.apache.james.nntpserver.repository.NNTPArticle#writeArticle(PrintWriter)
  +     * @see 
org.apache.james.nntpserver.repository.NNTPArticle#writeArticle(OutputStream)
        */
  -    public void writeArticle(PrintWriter prt) {
  -        BufferedReader reader = null;
  +    public void writeArticle(OutputStream out) {
  +        FileInputStream fileStream = null;
           try {
  -            reader = new BufferedReader(new FileReader(articleFile));
  -            String line = null;
  -            while ( ( line = reader.readLine() ) != null ) {
  -                // add extra dot if line starts with '.'
  -                // '.' indicates end of article.
  -                if ( line.startsWith(".") )
  -                    prt.print(".");
  -                prt.println(line);
  +            fileStream = new FileInputStream(articleFile);
  +            byte[] readBuffer = new byte[1024];
  +            int read = 0;
  +            while ((read = fileStream.read(readBuffer)) > 0) {
  +                out.write(readBuffer, 0, read);
               }
  -        } catch(IOException ex) {
  +        } catch(IOException ex) { 
               throw new NNTPException(ex);
           } finally {
  -            try {
  -                if (reader != null) {
  -                    reader.close();
  +            if (fileStream != null) {
  +                try {
  +                    fileStream.close();
  +                } catch (IOException ioe) {
  +                    // Ignored
                   }
  -            } catch (IOException ioe) {
  -                throw new NNTPException(ioe);
               }
           }
       }
   
       /**
  -     * @see 
org.apache.james.nntpserver.repository.NNTPArticle#writeHead(PrintWriter)
  +     * @see 
org.apache.james.nntpserver.repository.NNTPArticle#writeHead(OutputStream)
        */
  -    public void writeHead(PrintWriter prt) {
  +    public void writeHead(OutputStream out) {
  +        FileInputStream fileStream = null;
           try {
  -            BufferedReader reader = new BufferedReader(new FileReader(articleFile));
  -            String line = null;
  -            while ( ( line = reader.readLine() ) != null ) {
  -                if ( line.trim().length() == 0 )
  -                    break;
  -                if ( line.startsWith(".") )
  -                    prt.print(".");
  -                prt.println(line);
  +            fileStream = new FileInputStream(articleFile);
  +            MailHeaders headers = new MailHeaders(fileStream);
  +            byte[] headerBuffer = headers.toByteArray();
  +            int headerBufferLength = headerBuffer.length;
  +            // Write the headers excluding the final CRLF pair
  +            if (headerBufferLength > 2) {
  +                out.write(headerBuffer, 0, (headerBufferLength - 2));
  +            }
  +        } catch(Exception ex) { 
  +            throw new NNTPException(ex);
  +        } finally {
  +            if (fileStream != null) {
  +                try {
  +                    fileStream.close();
  +                } catch (IOException ioe) {
  +                    // Ignored
  +                }
               }
  -            reader.close();
  -        } catch(IOException ex) { throw new NNTPException(ex); }
  +        }
       }
   
       /**
  -     * @see 
org.apache.james.nntpserver.repository.NNTPArticle#writeBody(PrintWriter)
  +     * @see 
org.apache.james.nntpserver.repository.NNTPArticle#writeBody(OutputStream)
        */
  -    public void writeBody(PrintWriter prt) {
  +    public void writeBody(OutputStream out) {
  +        FileInputStream fileStream = null;
           try {
  -            BufferedReader reader = new BufferedReader(new FileReader(articleFile));
  -            String line = null;
  -            boolean startWriting = false;
  -            while ( ( line = reader.readLine() ) != null ) {
  -                if ( startWriting ) {
  -                    if ( line.startsWith(".") )
  -                        prt.print(".");
  -                    prt.println(line);
  -                } else
  -                    startWriting = ( line.trim().length() == 0 );
  +            fileStream = new FileInputStream(articleFile);
  +            MailHeaders headers = new MailHeaders(fileStream);
  +            byte[] readBuffer = new byte[1024];
  +            int read = 0;
  +            while ((read = fileStream.read(readBuffer)) > 0) {
  +                out.write(readBuffer, 0, read);
               }
  -            reader.close();
  -        } catch(IOException ex) { throw new NNTPException(ex); }
  +        } catch(Exception ex) {
  +            throw new NNTPException(ex);
  +        } finally {
  +            if (fileStream != null) {
  +                try {
  +                    fileStream.close();
  +                } catch (IOException ioe) {
  +                    // Ignored
  +                }
  +            }
  +        }
       }
   
       /**
  -     * @see 
org.apache.james.nntpserver.repository.NNTPArticle#writeOverview(PrintWriter)
  +     * @see 
org.apache.james.nntpserver.repository.NNTPArticle#writeOverview(OutputStream)
        */
  -    public void writeOverview(PrintWriter prt) {
  +    public void writeOverview(OutputStream out) {
  +        FileInputStream fileStream = null;
           try {
  -            FileInputStream fin = new FileInputStream(articleFile);
  -            InternetHeaders hdr = new InternetHeaders(fin);
  -            fin.close();
  +            fileStream = new FileInputStream(articleFile);
  +            InternetHeaders hdr = new InternetHeaders(fileStream);
               String subject = hdr.getHeader("Subject",null);
               String author = hdr.getHeader("From",null);
               String date = hdr.getHeader("Date",null);
  @@ -212,16 +223,27 @@
               // TODO: Address the line count issue.
               long lineCount = -1;
               StringBuffer line=new StringBuffer(256)
  -                .append(getArticleNumber())      .append("\t")
  +                .append(getArticleNumber())    .append("\t")
                   .append(cleanHeader(subject))    .append("\t")
                   .append(cleanHeader(author))     .append("\t")
                   .append(cleanHeader(date))       .append("\t")
                   .append(cleanHeader(msgId))      .append("\t")
                   .append(cleanHeader(references)) .append("\t")
                   .append(byteCount)               .append("\t")
  -                .append(lineCount);
  -            prt.println(line.toString());
  -        } catch(Exception ex) { throw new NNTPException(ex); }
  +                .append(lineCount).append("\r\n");
  +            String lineString = line.toString();
  +            out.write(lineString.getBytes("ASCII"));
  +        } catch(Exception ex) {
  +            throw new NNTPException(ex);
  +        } finally {
  +            if (fileStream != null) {
  +                try {
  +                    fileStream.close();
  +                } catch (IOException ioe) {
  +                    // Ignored
  +                }
  +            }
  +        }
       }
   
       /**
  @@ -252,7 +274,7 @@
           StringBuffer sb = new StringBuffer(field);
           for( int i=0 ; i<sb.length() ; i++ ) {
               char c = sb.charAt(i);
  -            if( (c=='\n') || (c=='\t') || (c=='\r') ) {
  +            if( (c=='\n') || (c=='\t') || (c=='\r')) {
                   sb.setCharAt(i, ' ');
               }
           }
  
  
  
  1.5.4.3   +4 -4      
jakarta-james/src/java/org/apache/james/nntpserver/repository/NNTPRepository.java
  
  Index: NNTPRepository.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-james/src/java/org/apache/james/nntpserver/repository/NNTPRepository.java,v
  retrieving revision 1.5.4.2
  retrieving revision 1.5.4.3
  diff -u -r1.5.4.2 -r1.5.4.3
  --- NNTPRepository.java       8 Mar 2003 21:54:05 -0000       1.5.4.2
  +++ NNTPRepository.java       26 Mar 2003 06:31:17 -0000      1.5.4.3
  @@ -58,13 +58,12 @@
   
   package org.apache.james.nntpserver.repository;
   
  +import java.io.InputStream;
   import java.util.Date;
   import java.util.Iterator;
   
   /**
    * Abstraction of entire NNTP Repository.
  - *
  - * @author Harmeet Bedi <[EMAIL PROTECTED]>
    */
   public interface NNTPRepository {
   
  @@ -88,10 +87,11 @@
   
       /**
        * Creates an article in the repository from the data in the reader.
  +     * TODO: Change this to be more OO and pass in a MimeMessage
        *
  -     * @param reader the reader that serves as a source for the article data
  +     * @param in the InputStream that serves as a source for the message data.
        */
  -    void createArticle(NNTPLineReader reader);
  +    void createArticle(InputStream in);
   
       /**
        * Gets all groups that match the wildmat string
  
  
  
  1.11.4.3  +88 -48    
jakarta-james/src/java/org/apache/james/nntpserver/repository/NNTPRepositoryImpl.java
  
  Index: NNTPRepositoryImpl.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-james/src/java/org/apache/james/nntpserver/repository/NNTPRepositoryImpl.java,v
  retrieving revision 1.11.4.2
  retrieving revision 1.11.4.3
  diff -u -r1.11.4.2 -r1.11.4.3
  --- NNTPRepositoryImpl.java   8 Mar 2003 21:54:05 -0000       1.11.4.2
  +++ NNTPRepositoryImpl.java   26 Mar 2003 06:31:17 -0000      1.11.4.3
  @@ -64,6 +64,7 @@
   import org.apache.avalon.framework.configuration.Configurable;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.ConfigurationException;
  +import org.apache.avalon.framework.container.ContainerUtil;
   import org.apache.avalon.framework.context.Context;
   import org.apache.avalon.framework.context.ContextException;
   import org.apache.avalon.framework.context.Contextualizable;
  @@ -76,6 +77,7 @@
   
   import java.io.File;
   import java.io.FileOutputStream;
  +import java.io.InputStream;
   import java.io.IOException;
   import java.io.PrintStream;
   import java.util.ArrayList;
  @@ -83,15 +85,14 @@
   import java.util.HashMap;
   import java.util.Iterator;
   import java.util.List;
  +import java.util.Set;
   
   /**
    * NNTP Repository implementation.
  - *
  - * @author Harmeet Bedi <[EMAIL PROTECTED]>
    */
   public class NNTPRepositoryImpl extends AbstractLogEnabled 
  -    implements NNTPRepository, Contextualizable, Configurable, Initializable
  -{
  +    implements NNTPRepository, Contextualizable, Configurable, Initializable {
  +
       /**
        * The context employed by this repository
        */
  @@ -128,9 +129,9 @@
       private ArticleIDRepository articleIDRepo;
   
       /**
  -     * The list of groups stored in this repository
  +     * A map to allow lookup of valid newsgroup names
        */
  -    private String[] addGroups = null;
  +    private HashMap groupNameMap = null;
   
       /**
        * The root path as a String.
  @@ -186,22 +187,41 @@
       public void configure( Configuration aConfiguration ) throws 
ConfigurationException {
           configuration = aConfiguration;
           readOnly = configuration.getChild("readOnly").getValueAsBoolean(false);
  +        articleIDDomainSuffix = configuration.getChild("articleIDDomainSuffix")
  +            .getValue("foo.bar.sho.boo");
  +        rootPathString = configuration.getChild("rootPath").getValue(null);
  +        if (rootPathString == null) {
  +            throw new ConfigurationException("Root path URL is required.");
  +        }
  +        tempPathString = configuration.getChild("tempPath").getValue(null);
  +        if (tempPathString == null) {
  +            throw new ConfigurationException("Temp path URL is required.");
  +        }
  +        articleIdPathString = 
configuration.getChild("articleIDPath").getValue(null);
  +        if (articleIdPathString == null) {
  +            throw new ConfigurationException("Article ID path URL is required.");
  +        }
  +        if (getLogger().isDebugEnabled()) {
  +            if (readOnly) {
  +                getLogger().debug("NNTP repository is read only.");
  +            } else {
  +                getLogger().debug("NNTP repository is writeable.");
  +            }
  +            getLogger().debug("NNTP repository root path URL is " + rootPathString);
  +            getLogger().debug("NNTP repository temp path URL is " + tempPathString);
  +            getLogger().debug("NNTP repository article ID path URL is " + 
articleIdPathString);
  +        }
           Configuration newsgroupConfiguration = configuration.getChild("newsgroups");
  -        List addGroupsList = new ArrayList();
  -        if ( configuration != null ) {
  +        groupNameMap = new HashMap();
  +        if ( newsgroupConfiguration != null ) {
               Configuration[] children = 
newsgroupConfiguration.getChildren("newsgroup");
               if ( children != null ) {
                   for ( int i = 0 ; i < children.length ; i++ ) {
  -                    addGroupsList.add(children[i].getValue());
  +                    String groupName = children[i].getValue();
  +                    groupNameMap.put(groupName, groupName);
                   }
               }
           }
  -        articleIDDomainSuffix = configuration.getChild("articleIDDomainSuffix")
  -            .getValue("foo.bar.sho.boo");
  -        addGroups = (String[])addGroupsList.toArray(new String[0]);
  -        rootPathString = configuration.getChild("rootPath").getValue();
  -        tempPathString = configuration.getChild("tempPath").getValue();
  -        articleIdPathString = configuration.getChild("articleIDPath").getValue();
           getLogger().debug("Repository configuration done");
       }
   
  @@ -210,6 +230,7 @@
        */
       public void initialize() throws Exception {
   
  +        getLogger().debug("Starting initialize");
           File articleIDPath = null;
   
           try {
  @@ -246,15 +267,18 @@
               throw new ConfigurationException(errorBuffer.toString());
           }
   
  -        for ( int i = 0 ; i < addGroups.length ; i++ ) {
  -            File groupFile = new File(rootPath,addGroups[i]);
  +        Set groups = groupNameMap.keySet();
  +        Iterator groupIterator = groups.iterator();
  +        while( groupIterator.hasNext() ) {
  +            String groupName = (String)groupIterator.next();
  +            File groupFile = new File(rootPath,groupName);
               if ( groupFile.exists() == false ) {
                   groupFile.mkdirs();
               } else if (!(groupFile.isDirectory())) {
                   StringBuffer errorBuffer =
                       new StringBuffer(128)
                           .append("A file exists in the NNTP root directory with the 
same name as a newsgroup.  File ")
  -                        .append(addGroups[i])
  +                        .append(groupName)
                           .append("in directory ")
                           .append(rootPathString)
                           .append(" is not a directory.");
  @@ -286,14 +310,27 @@
        * @see org.apache.james.nntpserver.repository.NNTPRepository#getGroup(String)
        */
       public NNTPGroup getGroup(String groupName) {
  +        if (groupNameMap.get(groupName) == null) {
  +            if (getLogger().isDebugEnabled()) {
  +                getLogger().debug(groupName + " is not a newsgroup hosted on this 
server.");
  +            }
  +            return null;
  +        }
           File groupFile = new File(rootPath,groupName);
           NNTPGroup groupToReturn = null;
           synchronized(this) {
               groupToReturn = (NNTPGroup)repositoryGroups.get(groupName);
               if ((groupToReturn == null) && groupFile.exists() && 
groupFile.isDirectory() ) {
  -                groupToReturn = new NNTPGroupImpl(groupFile);
  -                ((NNTPGroupImpl)groupToReturn).enableLogging(getLogger());
  -                repositoryGroups.put(groupName, groupToReturn);
  +                try {
  +                    groupToReturn = new NNTPGroupImpl(groupFile);
  +                    ContainerUtil.enableLogging(groupToReturn, getLogger());
  +                    ContainerUtil.contextualize(groupToReturn, context);
  +                    ContainerUtil.initialize(groupToReturn);
  +                    repositoryGroups.put(groupName, groupToReturn);
  +                } catch (Exception e) {
  +                    getLogger().error("Couldn't create group object.", e);
  +                    groupToReturn = null;
  +                }
               }
           }
           return groupToReturn;
  @@ -309,34 +346,43 @@
               ex.printStackTrace();
               return null;
           }
  -//         int idx = id.indexOf('@');
  -//         String name = id.substring(0,idx);
  -//         String groupname = id.substring(idx+1);
  -//         NNTPGroup group = getGroup(groupname);
  -//         return ( group == null ) ? null : group.getArticleFromID(name);
       }
   
       /**
  -     * @see 
org.apache.james.nntpserver.repository.NNTPRepository#createArticle(NNTPLineReader)
  +     * @see 
org.apache.james.nntpserver.repository.NNTPRepository#createArticle(InputStream)
        */
  -    public void createArticle(NNTPLineReader reader) {
  +    public void createArticle(InputStream in) {
           StringBuffer fileBuffer =
               new StringBuffer(32)
                       .append(System.currentTimeMillis())
                       .append(".")
                       .append(Math.random());
           File f = new File(tempPath, fileBuffer.toString());
  +        FileOutputStream fout = null;
           try {
  -            FileOutputStream fout = new FileOutputStream(f);
  -            PrintStream prt = new PrintStream(fout,true);
  -            String line;
  -            while ( ( line = reader.readLine() ) != null ) {
  -                prt.println(line);
  +            fout = new FileOutputStream(f);
  +            byte[] readBuffer = new byte[1024];
  +            int bytesRead = 0;
  +            while ( ( bytesRead = in.read(readBuffer, 0, 1024) ) > 0 ) {
  +                fout.write(readBuffer, 0, bytesRead);
  +            }
  +            fout.flush();
  +            fout.close();
  +            fout = null;
  +            boolean renamed = f.renameTo(new 
File(spool.getSpoolPath(),f.getName()));
  +            if (!renamed) {
  +                throw new IOException("Could not create article on the spool.");
               }
  -            prt.close();
  -            f.renameTo(new File(spool.getSpoolPath(),f.getName()));
           } catch(IOException ex) {
               throw new NNTPException("create article failed",ex);
  +        } finally {
  +            if (fout != null) {
  +                try {
  +                    fout.close();
  +                } catch (IOException ioe) {
  +                    // Ignored
  +                }
  +            }
           }
       }
   
  @@ -344,6 +390,7 @@
        * @see 
org.apache.james.nntpserver.repository.NNTPRepository#getMatchedGroups(String)
        */
       public Iterator getMatchedGroups(String wildmat) {
  +        // TODO: Add filter for valid group names
           File[] f = rootPath.listFiles(new AndFileFilter
               (new DirectoryFileFilter(),new GlobFilenameFilter(wildmat)));
           return getGroups(f);
  @@ -371,6 +418,7 @@
        * @see 
org.apache.james.nntpserver.repository.NNTPRepository#getGroupsSince(Date)
        */
       public Iterator getGroupsSince(Date dt) {
  +        // TODO: Add filter for valid group names
           File[] f = rootPath.listFiles(new AndFileFilter
               (new DirectoryFileFilter(),new DateSinceFileFilter(dt.getTime())));
           return getGroups(f);
  @@ -441,19 +489,11 @@
           }
           try {
               Object obj = 
getClass().getClassLoader().loadClass(className).newInstance();
  -            // TODO: Need to support compose
  -            if ( obj instanceof LogEnabled ) {
  -                ((LogEnabled)obj).enableLogging( getLogger() );
  -            }
  -            if (obj instanceof Contextualizable) {
  -                ((Contextualizable)obj).contextualize(context);
  -            }
  -            if ( obj instanceof Configurable ) {
  -                
((Configurable)obj).configure(spoolerConfiguration.getChild("configuration"));
  -            }
  -            if ( obj instanceof Initializable ) {
  -                ((Initializable)obj).initialize();
  -            }
  +            // TODO: Need to support service
  +            ContainerUtil.enableLogging(obj, getLogger());
  +            ContainerUtil.contextualize(obj, context);
  +            ContainerUtil.configure(obj, 
spoolerConfiguration.getChild("configuration"));
  +            ContainerUtil.initialize(obj);
               return (NNTPSpooler)obj;
           } catch(ClassCastException cce) {
               StringBuffer errorBuffer =
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to