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]