geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jlaskow...@apache.org
Subject svn commit: r384292 [1/2] - in /geronimo/trunk/modules/javamail-transport: ./ src/java/org/apache/geronimo/javamail/authentication/ src/java/org/apache/geronimo/javamail/store/nntp/ src/java/org/apache/geronimo/javamail/store/nntp/newsrc/ src/java/org/...
Date Wed, 08 Mar 2006 18:04:33 GMT
Author: jlaskowski
Date: Wed Mar  8 10:04:19 2006
New Revision: 384292

URL: http://svn.apache.org/viewcvs?rev=384292&view=rev
Log:
GERONIMO-1712 Add NNTP Store support to javamail

+ propset svn:keywords 'Rev Date'

Added:
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPFolder.java   (with props)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPGroupFolder.java   (with props)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPMessage.java   (with props)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPRootFolder.java   (with props)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPStore.java   (with props)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrc.java   (with props)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcFile.java   (with props)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcGroup.java   (with props)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/Range.java   (with props)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/RangeList.java   (with props)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/nntp/StringListInputStream.java   (with props)
Modified:
    geronimo/trunk/modules/javamail-transport/LICENSE.txt   (props changed)
    geronimo/trunk/modules/javamail-transport/NOTICE.txt   (props changed)
    geronimo/trunk/modules/javamail-transport/project.xml   (contents, props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/authentication/ClientAuthenticator.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/authentication/CramMD5Authenticator.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/authentication/DigestMD5Authenticator.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/authentication/LoginAuthenticator.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/authentication/PlainAuthenticator.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/POP3Command.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/POP3CommandFactory.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/POP3Connection.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/POP3Constants.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/POP3Folder.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/POP3Response.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/POP3ResponseBuilder.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/POP3Store.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/message/POP3Message.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageFactory.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageWithContentInfo.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageWithEnvelope.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/message/POP3MessageWithFlags.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/response/DefaultPOP3Response.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/response/POP3ListResponse.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/response/POP3ResponseFactory.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/pop3/response/POP3StatusResponse.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/nntp/NNTPConnection.java
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/nntp/NNTPReply.java
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/nntp/NNTPTransport.java
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/smtp/MalformedSMTPReplyException.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/smtp/SMTPAddressFailedException.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/smtp/SMTPAddressSucceededException.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/smtp/SMTPMessage.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/smtp/SMTPReply.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/smtp/SMTPSTransport.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/smtp/SMTPSendFailedException.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/smtp/SMTPTransport.java   (props changed)
    geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/transport/smtp/SMTPTransportException.java   (contents, props changed)
    geronimo/trunk/modules/javamail-transport/src/resources/META-INF/javamail.default.providers

Propchange: geronimo/trunk/modules/javamail-transport/LICENSE.txt
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Wed Mar  8 10:04:19 2006
@@ -1 +1 @@
-Date Author Id Revision HeadURL
+Rev Date

Propchange: geronimo/trunk/modules/javamail-transport/NOTICE.txt
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Wed Mar  8 10:04:19 2006
@@ -1 +1 @@
-Date Author Id Revision HeadURL
+Rev Date

Modified: geronimo/trunk/modules/javamail-transport/project.xml
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/javamail-transport/project.xml?rev=384292&r1=384291&r2=384292&view=diff
==============================================================================
--- geronimo/trunk/modules/javamail-transport/project.xml (original)
+++ geronimo/trunk/modules/javamail-transport/project.xml Wed Mar  8 10:04:19 2006
@@ -17,7 +17,7 @@
 -->
   
 
-<!-- $Rev:$ $Date:$ -->
+<!-- $Rev$ $Date$ -->
 
 <project>
     <pomVersion>3</pomVersion>

Propchange: geronimo/trunk/modules/javamail-transport/project.xml
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Wed Mar  8 10:04:19 2006
@@ -1 +1 @@
-Date Author Id Revision HeadURL
+Rev Date

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/authentication/ClientAuthenticator.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Wed Mar  8 10:04:19 2006
@@ -1 +1 @@
-Date Author Id Revision HeadURL
+Rev Date

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/authentication/CramMD5Authenticator.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Wed Mar  8 10:04:19 2006
@@ -1 +1 @@
-Date Author Id Revision HeadURL
+Rev Date

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/authentication/DigestMD5Authenticator.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Wed Mar  8 10:04:19 2006
@@ -1 +1 @@
-Date Author Id Revision HeadURL
+Rev Date

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/authentication/LoginAuthenticator.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Wed Mar  8 10:04:19 2006
@@ -1 +1 @@
-Date Author Id Revision HeadURL
+Rev Date

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/authentication/PlainAuthenticator.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Wed Mar  8 10:04:19 2006
@@ -1 +1 @@
-Date Author Id Revision HeadURL
+Rev Date

Added: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPFolder.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPFolder.java?rev=384292&view=auto
==============================================================================
--- geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPFolder.java (added)
+++ geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPFolder.java Wed Mar  8 10:04:19 2006
@@ -0,0 +1,430 @@
+/**
+ *
+ * Copyright 2003-2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.geronimo.javamail.store.nntp;
+
+import java.util.Vector;
+
+import javax.mail.FetchProfile;
+import javax.mail.Flags;
+import javax.mail.Folder;
+import javax.mail.IllegalWriteException;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.MethodNotSupportedException;
+import javax.mail.Session;
+import javax.mail.Store;
+import javax.mail.URLName;
+import javax.mail.event.ConnectionEvent;
+
+import org.apache.geronimo.javamail.transport.nntp.NNTPConnection;
+import org.apache.geronimo.javamail.transport.nntp.NNTPReply;
+
+/**
+ * The base NNTP implementation of the javax.mail.Folder
+ * This is a base class for both the Root NNTP server and each NNTP group folder.
+ * @see javax.mail.Folder
+ *
+ * @version $Rev$
+ */
+public class NNTPFolder extends Folder {
+
+    // our active connection.
+    protected NNTPConnection connection;
+    // our attached session
+    protected Session session;
+    // the name of this folder (either the name of the server for the root or the news group name).
+    protected String name;
+    // the "full" name of the folder.  For the root folder, this is the name returned by the connection
+    // welcome string.  Otherwise, this is the same as the name.
+    protected String fullName;
+    // the parent folder.  For the root folder, this is null.  For a group folder, this is the root.
+    protected Folder parent;
+    // the folder open state
+	protected boolean folderOpen = false;
+    // the folder message count.  For the root folder, this is always 0.
+    protected int messageCount = 0;
+    // the persistent flags we save in the store (basically just the SEEN flag).
+    protected Flags permanentFlags;
+
+
+    /**
+     * Super class constructor the base NNTPFolder class.
+     *
+     * @param store  The javamail store this folder is attached to.
+     */
+	protected NNTPFolder(NNTPStore store) {
+		super(store);
+        // get the active connection from the store...all commands are sent there
+		this.connection = store.getConnection();
+		this.session = store.getSession();
+
+        // set up our permanent flags bit.
+        permanentFlags = new Flags();
+        permanentFlags.add(Flags.Flag.SEEN);
+	}
+
+    /**
+     * Retrieve the folder name.
+     *
+     * @return The folder's name.
+     */
+	public String getName() {
+        return name;
+	}
+
+    /**
+     * Retrieve the folder's full name (including hierarchy information).
+     * NNTP folders are flat, so the full name is generally the same
+     * as the name.
+     *
+     * @return The full name value.
+     */
+	public String getFullName() {
+        return fullName;
+	}
+
+	/**
+	 * Returns the parent folder for this folder.  Returns null if this is the
+     * root folder.
+	 */
+	public Folder getParent() throws MessagingException {
+        return parent;
+	}
+
+    /**
+     * Indicated whether the folder "exists" or not.  Existance in this
+     * context indicates that the group still exists on the server.
+     *
+     * @return
+     * @exception MessagingException
+     */
+	public boolean exists() throws MessagingException {
+        // by default, return true.  This is really only the case for the root.  The group folder will
+        // need to override this.
+		return true;
+	}
+
+
+    /**
+     * List the subfolders.  For group folders, this is a meaningless
+     * so we throw a MethodNotSupportedException.
+     *
+     * @param pattern The folder pattern string.
+     *
+     * @return Never returns.
+     * @exception MessagingException
+     */
+	public Folder[] list(String pattern) throws MessagingException {
+		throw new MethodNotSupportedException("NNTP group folders cannot contain sub folders");
+	}
+
+    /**
+     * Retrieve the list of subscribed folders that match the given
+     * pattern string.
+     *
+     * @param pattern The pattern string used for the matching
+     *
+     * @return An array of matching folders from the subscribed list.
+     */
+    public Folder[] listSubscribed(String pattern) throws MessagingException {
+		throw new MethodNotSupportedException("NNTP group folders cannot contain sub folders");
+    }
+
+	/**
+	 * No sub folders, hence there is no notion of a seperator.  We return a null character (consistent
+     * with what Sun returns for POP3 folders).
+	 */
+	public char getSeparator() throws MessagingException {
+        return '\0';
+	}
+
+    /**
+     * Return whether this folder can hold just messages or also
+     * subfolders.  Only the root folder can hold other folders,
+     * so it will need to override.
+     *
+     * @return Either Folder.HOLDS_MESSAGES or Folder.HOLDS_FOLDERS.
+     * @exception MessagingException
+     */
+	public int getType() throws MessagingException {
+		return HOLDS_MESSAGES;
+	}
+
+    /**
+     * Create a new folder.  NNTP folders are read only, so this is a nop.
+     *
+     * @param type   The type of folder.
+     *
+     * @return Not support, throws an exception.
+     * @exception MessagingException
+     */
+	public boolean create(int type) throws MessagingException {
+		throw new MethodNotSupportedException("Sub folders cannot be created in NNTP");
+	}
+
+    /**
+     * Check for new messages.  We always return false for the
+     * root folder.  The group folders will need to override.
+     *
+     * @return Always returns false.
+     * @exception MessagingException
+     */
+	public boolean hasNewMessages() throws MessagingException {
+        return false;
+	}
+
+    /**
+     * Get a named subfolder from this folder.  This only has
+     * meaning from the root NNTP folder.
+     *
+     * @param name   The requested name.
+     *
+     * @return If the folder exists, returns a Folder object representing the
+     *         named folder.
+     * @exception MessagingException
+     */
+	public Folder getFolder(String name) throws MessagingException {
+		throw new MethodNotSupportedException("NNTP Group folders do not support sub folders");
+	}
+
+    /**
+     * Delete a folder.  This is not supported for NNTP.
+     *
+     * @param recurse The recusion flag.
+     *
+     * @return Never returns.
+     * @exception MessagingException
+     */
+	public boolean delete(boolean recurse) throws MessagingException {
+		throw new MethodNotSupportedException("Deleting of NNTP folders is not supported");
+	}
+
+    /**
+     * Rename a folder.  Not supported for NNTP folders.
+     *
+     * @param f      The new folder specifying the rename location.
+     *
+     * @return
+     * @exception MessagingException
+     */
+	public boolean renameTo(Folder f) throws MessagingException {
+		throw new MethodNotSupportedException("Renaming of NNTP folders is not supported.");
+	}
+
+	/**
+	 * @see javax.mail.Folder#open(int)
+	 */
+	public void open(int mode) throws MessagingException {
+
+        // we don't support READ_WRITE mode, so don't allow opening in that mode.
+        if (mode == READ_WRITE) {
+            throw new IllegalWriteException("Newsgroup folders cannot be opened read/write");
+        }
+
+
+		// an only be performed on a closed folder
+		checkClosed();
+
+		this.mode = mode;
+
+        // perform folder type-specific open actions.
+        openFolder();
+
+        folderOpen = true;
+
+		notifyConnectionListeners(ConnectionEvent.OPENED);
+	}
+
+    /**
+     * Perform folder type-specific open actions.  The default
+     * action is to do nothing.
+     *
+     * @exception MessagingException
+     */
+    protected void openFolder() throws MessagingException {}
+
+    /**
+     * Peform folder type-specific close actions.  The default action
+     * is to do nothing.
+     *
+     * @exception MessagingException
+     */
+    protected void closeFolder() throws MessagingException {}
+
+    /**
+     * Close the folder.  Cleans up resources, potentially expunges
+     * messages marked for deletion, and sends an event notification.
+     *
+     * @param expunge The expunge flag, which is ignored for NNTP folders.
+     *
+     * @exception MessagingException
+     */
+	public void close(boolean expunge) throws MessagingException {
+		// Can only be performed on an open folder
+		checkOpen();
+
+        // give the subclasses an opportunity to do some cleanup
+        closeFolder();
+
+		folderOpen = false;
+		notifyConnectionListeners(ConnectionEvent.CLOSED);
+	}
+
+    /**
+     * Tests the open status of the folder.
+     *
+     * @return true if the folder is open, false otherwise.
+     */
+	public boolean isOpen() {
+		return folderOpen;
+	}
+
+    /**
+     * Get the permanentFlags
+     *
+     * @return The set of permanent flags we support (only SEEN).
+     */
+	public Flags getPermanentFlags() {
+        // we need a copy of our master set.
+		return new Flags(permanentFlags);
+	}
+
+    /**
+     * Get the count of messages in this folder.
+     *
+     * @return The message count.
+     * @exception MessagingException
+     */
+	public int getMessageCount() throws MessagingException {
+		return messageCount;
+	}
+
+	/**
+	 * Checks wether the message is in cache, if not
+	 * will create a new message object and return it.
+	 * @see javax.mail.Folder#getMessage(int)
+	 */
+	public Message getMessage(int msgNum) throws MessagingException {
+        // for the base, we just throw an exception.
+        throw new MethodNotSupportedException("Root NNTP folder does not contain messages");
+	}
+
+    /**
+     * Append messages to a folder.  NNTP folders are read only, so this
+     * is not supported.
+     *
+     * @param msgs   The list of messages to append.
+     *
+     * @exception MessagingException
+     */
+	public void appendMessages(Message[] msgs) throws MessagingException {
+        throw new MethodNotSupportedException("Root NNTP folder does not contain messages");
+
+	}
+
+    /**
+     * Expunge messages marked for deletion and return a list of the
+     * Messages.  Not supported for NNTP.
+     *
+     * @return Never returns.
+     * @exception MessagingException
+     */
+	public Message[] expunge() throws MessagingException {
+        throw new MethodNotSupportedException("Root NNTP folder does not contain messages");
+	}
+
+
+	/**
+	 * Below is a list of convenience methods that avoid repeated checking for a
+	 * value and throwing an exception
+	 */
+
+    /** Ensure the folder is open */
+    protected void checkOpen() throws IllegalStateException {
+		if (!folderOpen){
+		    throw new IllegalStateException("Folder is not Open");
+		}
+    }
+
+    /** Ensure the folder is not open */
+    protected void checkClosed() throws IllegalStateException {
+		if (folderOpen){
+		    throw new IllegalStateException("Folder is Open");
+		}
+    }
+
+    /**
+     * @see javax.mail.Folder#notifyMessageChangedListeners(int, javax.mail.Message)
+     *
+     * this method is protected and cannot be used outside of Folder, therefore had to
+     * explicitly expose it via a method in NNTPFolder, so that NNTPMessage has access to it
+     *
+     * Bad design on the part of the Java Mail API.
+     */
+    public void notifyMessageChangedListeners(int type, Message m) {
+    	super.notifyMessageChangedListeners(type, m);
+    }
+
+
+    /**
+     * Retrieve the subscribed status for a folder.  This default
+     * implementation just returns false (which is true for the
+     * root folder).
+     *
+     * @return Always returns true.
+     */
+    public boolean isSubscribed() {
+        return false;
+    }
+
+    /**
+     * Set the subscribed status for a folder.
+     *
+     * @param flag   The new subscribed status.
+     *
+     * @exception MessagingException
+     */
+    public void setSubscribed(boolean flag) throws MessagingException {
+        throw new MessagingException("Root NNTP folder cannot be subscribed to");
+    }
+
+    /**
+     * Test if a given article number is marked as SEEN.
+     *
+     * @param article The target article number.
+     *
+     * @return The articles current seen status.
+     */
+    public boolean isSeen(int article) {
+        return false;
+    }
+
+    /**
+     * Set the SEEN status for an article.
+     *
+     * @param article The target article.
+     * @param flag    The new seen setting.
+     *
+     * @exception MessagingException
+     */
+    public void setSeen(int article, boolean flag) throws MessagingException {
+        throw new MessagingException("Root NNTP folder does not contain articles");
+    }
+
+}
+

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPFolder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPFolder.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPGroupFolder.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPGroupFolder.java?rev=384292&view=auto
==============================================================================
--- geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPGroupFolder.java (added)
+++ geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPGroupFolder.java Wed Mar  8 10:04:19 2006
@@ -0,0 +1,379 @@
+/**
+ *
+ * Copyright 2003-2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.geronimo.javamail.store.nntp;
+
+import java.util.StringTokenizer;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+
+import javax.mail.FetchProfile;
+import javax.mail.Flags;
+import javax.mail.Folder;
+import javax.mail.FolderNotFoundException;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.MethodNotSupportedException;
+import javax.mail.Session;
+import javax.mail.Store;
+import javax.mail.URLName;
+import javax.mail.event.ConnectionEvent;
+
+import org.apache.geronimo.javamail.store.nntp.newsrc.NNTPNewsrcGroup;
+
+import org.apache.geronimo.javamail.transport.nntp.NNTPConnection;
+import org.apache.geronimo.javamail.transport.nntp.NNTPReply;
+
+/**
+ * The NNTP implementation of the javax.mail.Folder
+ * Note that only INBOX is supported in NNTP
+ * <p>
+ * <url>http://www.faqs.org/rfcs/rfc1939.html</url>
+ * </p>
+ * @see javax.mail.Folder
+ *
+ * @version $Rev$ $Date$
+ */
+public class NNTPGroupFolder extends NNTPFolder {
+
+    // holders for status information returned by the GROUP command.
+    protected int firstArticle = -1;
+    protected int lastArticle = -1;
+
+    // retrieved articles, mapped by article number.
+    Map articles;
+
+    // information stored in the newsrc group.
+    NNTPNewsrcGroup groupInfo;
+
+    /**
+     * Construct a "real" folder representing an NNTP news group.
+     *
+     * @param parent    The parent root folder.
+     * @param store     The Store this folder is attached to.
+     * @param name      The folder name.
+     * @param groupInfo The newsrc group information attached to the newsrc database.  This
+     *                  contains subscription and article "SEEN" information.
+     */
+	protected NNTPGroupFolder(NNTPRootFolder parent, NNTPStore store, String name, NNTPNewsrcGroup groupInfo) {
+		super(store);
+        // the name and the full name are the same.
+        this.name = name;
+        this.fullName = name;
+        // set the parent appropriately.
+        this.parent = parent = parent;
+        this.groupInfo = groupInfo;
+	}
+
+    /**
+     * Ping the server and update the group count, first, and last
+     * information.
+     *
+     * @exception MessagingException
+     */
+    private void updateGroupStats() throws MessagingException {
+        // ask the server for information about the group.  This is a one-line reponse with status on
+        // the group, if it exists.
+        NNTPReply reply = connection.sendCommand("GROUP " + name);
+
+        // explicitly not there?
+        if (reply.getCode() == NNTPReply.NO_SUCH_NEWSGROUP) {
+            throw new FolderNotFoundException(this, "Folder does not exist on server: " + reply);
+        }
+        else if (reply.getCode() != NNTPReply.GROUP_SELECTED) {
+            throw new MessagingException("Error requesting group information: " + reply);
+        }
+
+        // we've gotten back a good response, now parse out the group specifics from the
+        // status response.
+
+        StringTokenizer tokenizer = new StringTokenizer(reply.getMessage());
+
+        // we should have a least 3 tokens here, in the order "count first last".
+
+        // article count
+        if (tokenizer.hasMoreTokens()) {
+            String count = tokenizer.nextToken();
+            try {
+                messageCount = Integer.parseInt(count);
+            } catch (NumberFormatException e) {
+                // ignore
+            }
+        }
+
+        // first article number
+        if (tokenizer.hasMoreTokens()) {
+            String first = tokenizer.nextToken();
+            try {
+                firstArticle = Integer.parseInt(first);
+            } catch (NumberFormatException e) {
+                // ignore
+            }
+        }
+
+        // last article number.
+        if (tokenizer.hasMoreTokens()) {
+            String last = tokenizer.nextToken();
+            try {
+                lastArticle = Integer.parseInt(last);
+            } catch (NumberFormatException e) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Test to see if this folder actually exists.  This pings the
+     * server for information about the GROUP and updates the
+     * article count and index information.
+     *
+     * @return true if the newsgroup exists on the server, false otherwise.
+     * @exception MessagingException
+     */
+	public boolean exists() throws MessagingException {
+
+        try {
+            // update the group statistics.  If the folder doesn't exist, we'll get an exception that we
+            // can turn into a false reply.
+            updateGroupStats();
+            // updated ok, so it must be there.
+            return true;
+        } catch (FolderNotFoundException e ) {
+            return false;
+        }
+	}
+
+    /**
+     * Ping the NNTP server to check if a newsgroup has any new
+     * messages.
+     *
+     * @return True if the server has new articles from the last time we
+     *         checked.  Also returns true if this is the first time we've
+     *         checked.
+     * @exception MessagingException
+     */
+	public boolean hasNewMessages() throws MessagingException {
+        int oldLast = lastArticle;
+        updateGroupStats();
+
+        return lastArticle > oldLast;
+	}
+
+
+    /**
+     * Open the folder for use.  This retrieves article count information
+     * from the server.
+     *
+     * @exception MessagingException
+     */
+	public void openFolder() throws MessagingException {
+        // update the group specifics, especially the message count.
+        updateGroupStats();
+
+        // get a cache for retrieve articles
+        articles = new HashMap();
+	}
+
+
+    /**
+     * Close the folder, which also clears out the article caches.
+     *
+     * @exception MessagingException
+     */
+	public void closeFolder() throws MessagingException {
+        // get ride of any retrieve articles, and flip over the open for business sign.
+        articles = null;
+	}
+
+	/**
+	 * Checks wether the message is in cache, if not
+	 * will create a new message object and return it.
+	 * @see javax.mail.Folder#getMessage(int)
+	 */
+	public Message getMessage(int msgNum) throws MessagingException {
+		// Can only be performed on an Open folder
+		checkOpen();
+
+        // get an object form to look up in the retrieve messages list (oh how I wish there was
+        // something like Map that could use integer keys directly!).
+        Integer key = new Integer(msgNum);
+        NNTPMessage message = (NNTPMessage)articles.get(key);
+        if (message != null) {
+            // piece of cake!
+            return message;
+        }
+
+        // we need to suck a message down from the server.
+        // but first, make sure the group is still valid.
+        updateGroupStats();
+
+        // just send a STAT command to this message.  Right now, all we want is existance proof.  We'll
+        // retrieve the other bits when requested.
+        NNTPReply reply = connection.sendCommand("STAT " + Integer.toString(msgNum));
+        if (reply.getCode() != NNTPReply.REQUEST_TEXT_SEPARATELY) {
+            throw new MessagingException("Error retrieving article from NNTP server: " + reply);
+        }
+
+        // we need to parse out the message id.
+        String response = reply.getMessage();
+
+        int idStart = response.indexOf('<');
+        int idEnd = response.indexOf('>');
+
+        message = new NNTPMessage(this, (NNTPStore)store, msgNum, response.substring(idStart + 1, idEnd));
+
+        // add this to the article cache.
+        articles.put(key, message);
+
+        return message;
+	}
+
+
+    /**
+     * Retrieve all articles in the group.
+     *
+     * @return An array of all messages in the group.
+     */
+    public Message[] getMessages() throws MessagingException {
+        // we're going to try first with XHDR, which will allow us to retrieve everything in one shot.  If that
+        // fails, we'll fall back on issing STAT commands for the entire article range.
+        NNTPReply reply = connection.sendCommand("XHDR Message-ID " + Integer.toString(firstArticle) + "-" + Integer.toString(lastArticle), NNTPReply.HEAD_FOLLOWS);
+
+        List messages = new ArrayList();
+
+        if (reply.getCode() == NNTPReply.HEAD_FOLLOWS) {
+            List lines = reply.getData();
+
+            for (int i = 0; i < lines.size(); i++) {
+                String line = (String)lines.get(i);
+
+                try {
+                    int pos = line.indexOf(' ');
+                    int articleID = Integer.parseInt(line.substring(0, pos));
+                    String messageID = line.substring(pos + 1);
+                    Integer key = new Integer(articleID);
+                    // see if we have this message cached,  If not, create it.
+                    Message message = (Message)articles.get(key);
+                    if (message == null) {
+                        message = new NNTPMessage(this, (NNTPStore)store, key.intValue(), messageID);
+                        articles.put(key, message);
+                    }
+
+                    messages.add(message);
+
+                } catch (NumberFormatException e) {
+                    // should never happen, but just skip this entry if it does.
+                }
+            }
+        }
+        else {
+            // grumble, we need to stat each article id to see if it exists....lots of round trips.
+            for (int i = firstArticle; i <= lastArticle; i++) {
+                try {
+                    messages.add(getMessage(i));
+                } catch (MessagingException e) {
+                    // just assume if there is an error, it's because the message id doesn't exist.
+                }
+            }
+        }
+
+        return (Message[])messages.toArray(new Message[0]);
+    }
+
+	/**
+	 * @see javax.mail.Folder#fetch(javax.mail.Message[], javax.mail.FetchProfile)
+	 *
+	 * The JavaMail API recommends that this method be overrident to provide a meaningfull
+	 * implementation.
+	 */
+	public void fetch(Message[] msgs, FetchProfile fp) throws MessagingException {
+		// Can only be performed on an Open folder
+		checkOpen();
+
+		for (int i=0; i < msgs.length;i++)
+		{
+			Message msg = msgs[i];
+            // we can only perform this operation for NNTPMessages.
+			if (msg == null || !(msg instanceof NNTPMessage)) {
+                // we can't fetch if it's the wrong message type
+                continue;
+			}
+
+            // fetching both the headers and body?
+            if (fp.contains(FetchProfile.Item.ENVELOPE) && fp.contains(FetchProfile.Item.CONTENT_INFO)) {
+
+                // retrive everything
+                ((NNTPMessage)msg).loadArticle();
+            }
+            // headers only?
+            else if (fp.contains(FetchProfile.Item.ENVELOPE)) {
+                ((NNTPMessage)msg).loadHeaders();
+            }
+            else if(fp.contains(FetchProfile.Item.CONTENT_INFO)) {
+                ((NNTPMessage)msg).loadContent();
+			}
+		}
+	}
+
+
+    /**
+     * Return the subscription status of this folder.
+     *
+     * @return true if the folder is marked as subscribed, false for unsubscribed.
+     */
+    public boolean isSubscribed() {
+        return groupInfo.isSubscribed();
+    }
+
+    /**
+     * Set or clear the subscription status of a file.
+     *
+     * @param flag   The new subscription state.
+     */
+    public void setSubscribed(boolean flag) {
+        groupInfo.setSubscribed(flag);
+    }
+
+    /**
+     * Return the "seen" state for an article in a folder.
+     *
+     * @param article The article number.
+     *
+     * @return true if the article is marked as seen in the newsrc file, false for
+     *         unseen files.
+     */
+    public boolean isSeen(int article) {
+        return groupInfo.isArticleSeen(article);
+    }
+
+    /**
+     * Set the seen state for an article in a folder.
+     *
+     * @param article The article number.
+     * @param flag    The new seen state.
+     */
+    public void setSeen(int article, boolean flag) {
+        if (flag) {
+            groupInfo.markArticleSeen(article);
+        }
+        else {
+            groupInfo.markArticleUnseen(article);
+        }
+    }
+}

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPGroupFolder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPGroupFolder.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPMessage.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPMessage.java?rev=384292&view=auto
==============================================================================
--- geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPMessage.java (added)
+++ geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPMessage.java Wed Mar  8 10:04:19 2006
@@ -0,0 +1,364 @@
+/**
+ *
+ * Copyright 2003-2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.geronimo.javamail.store.nntp;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Enumeration;
+
+import javax.mail.Flags;
+import javax.mail.Folder;
+import javax.mail.Header;
+import javax.mail.IllegalWriteException;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.Store;
+import javax.mail.event.MessageChangedEvent;
+import javax.mail.internet.InternetHeaders;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.geronimo.javamail.transport.nntp.NNTPConnection;
+import org.apache.geronimo.javamail.transport.nntp.NNTPReply;
+import org.apache.geronimo.javamail.transport.nntp.StringListInputStream;
+
+/**
+ * NNTP implementation of javax.mail.internet.MimeMessage
+ *
+ * Only the most basic information is given and
+ * Message objects created here is a light-weight reference to the actual Message
+ * As per the JavaMail spec items from the actual message will get filled up on demand
+ *
+ * If some other items are obtained from the server as a result of one call, then the other
+ * details are also processed and filled in. For ex if RETR is called then header information
+ * will also be processed in addition to the content
+ *
+ * @version $Rev$ $Date$
+ */
+public class NNTPMessage extends MimeMessage {
+    // the server message identifer
+    String messageID = null;
+
+    // our attached session
+    protected Session session;
+    // the Store we're stored in (which manages the connection and other stuff).
+    protected NNTPStore store;
+    // our active connection.
+    protected NNTPConnection connection;
+
+	// used to force loading of headers
+	protected boolean headersLoaded = false;
+    // use to force content loading
+    protected boolean contentLoaded = false;
+
+
+
+    /**
+     * Contruct an NNTPMessage instance.
+     *
+     * @param folder    The hosting folder for the message.
+     * @param store     The Store owning the article (and folder).
+     * @param msgnum    The article message number.
+     * @param messageID The article messageID (as assigned by the server).
+     *
+     * @exception MessagingException
+     */
+	NNTPMessage(NNTPFolder folder, NNTPStore store, int msgnum, String messageID) throws MessagingException {
+		super(folder, msgnum);
+        this.messageID = messageID;
+		this.store = store;
+		this.session = ((NNTPStore)store).getSession();
+        // get the active connection from the store...all commands are sent there
+		this.connection = ((NNTPStore)store).getConnection();
+
+        // get our flag set from the folder.
+        flags = folder.getPermanentFlags();
+        // now check our initial SEEN state and set the flags appropriately
+        if (folder.isSeen(msgnum)) {
+            flags.add(Flags.Flag.SEEN);
+        }
+        else {
+            flags.remove(Flags.Flag.SEEN);
+        }
+	}
+
+
+    /**
+     * Retrieve the size of the message content.  The content will
+     * be retrieved from the server, if necessary.
+     *
+     * @return The size of the content.
+     * @exception MessagingException
+     */
+	public int getSize() throws MessagingException {
+        // make sure we've retrieved the message content and continue with the superclass version.
+        loadContent();
+        return super.getSize();
+	}
+
+    /**
+     * Get a line count for the NNTP message.  This is potentially
+     * stored in the Lines article header.  If not there, we return
+     * a default of -1.
+     *
+     * @return The header line count estimate, or -1 if not retrieveable.
+     * @exception MessagingException
+     */
+    public int getLineCount() throws MessagingException {
+        String[] headers = getHeader("Lines");
+
+        // hopefully, there's only a single one of these.  No sensible way of interpreting
+        // multiples.
+        if (headers.length == 1) {
+            try {
+                return Integer.parseInt(headers[0].trim());
+
+            } catch (NumberFormatException e) {
+                // ignore
+            }
+        }
+        // dunno...and let them know I don't know.
+        return -1;
+    }
+
+
+
+	/**
+	 * @see javax.mail.internet.MimeMessage#getContentStream()
+	 */
+	protected InputStream getContentStream() throws MessagingException {
+        // get the article information.
+        loadArticle();
+		return super.getContentStream();
+	}
+
+
+	/******************************************************************
+	 * Following is a set of methods that deal with headers
+	 * These methods are just overrides on the superclass methods to
+     * allow lazy loading of the header information.
+	 ********************************************************************/
+
+	public String[] getHeader(String name) throws MessagingException {
+        loadHeaders();
+		return headers.getHeader(name);
+	}
+
+	public String getHeader(String name, String delimiter) throws MessagingException {
+        loadHeaders();
+		return headers.getHeader(name, delimiter);
+	}
+
+	public Enumeration getAllHeaders() throws MessagingException {
+        loadHeaders();
+		return headers.getAllHeaders();
+	}
+
+	public Enumeration getMatchingHeaders(String[] names)  throws MessagingException {
+        loadHeaders();
+		return headers.getMatchingHeaders(names);
+	}
+
+	public Enumeration getNonMatchingHeaders(String[] names) throws MessagingException {
+        loadHeaders();
+		return headers.getNonMatchingHeaders(names);
+	}
+
+	public Enumeration getAllHeaderLines() throws MessagingException {
+        loadHeaders();
+		return headers.getAllHeaderLines();
+	}
+
+	public Enumeration getMatchingHeaderLines(String[] names) throws MessagingException {
+        loadHeaders();
+		return headers.getMatchingHeaderLines(names);
+	}
+
+	public Enumeration getNonMatchingHeaderLines(String[] names) throws MessagingException {
+        loadHeaders();
+		return headers.getNonMatchingHeaderLines(names);
+	}
+
+	/**
+	 * We cannot modify these messages
+	 */
+	public void saveChanges() throws MessagingException {
+		throw new IllegalWriteException("NNTP messages are read-only");
+	}
+
+
+    /**
+     * Retrieve the message headers from the NNTP server.
+     *
+     * @exception MessagingException
+     */
+    public void loadHeaders() throws MessagingException {
+        // don't retrieve if already loaded.
+        if (headersLoaded) {
+            return;
+        }
+
+
+        NNTPReply reply = connection.sendCommand("HEAD " + messageID, NNTPReply.HEAD_FOLLOWS);
+
+        if (reply.getCode() == NNTPReply.HEAD_FOLLOWS) {
+            try {
+                // wrap a stream around the reply data and read as headers.
+                updateHeaders(new StringListInputStream(reply.getData()));
+            } catch (IOException e) {
+                throw new MessagingException("Error retrieving article headers from server", e);
+            }
+        }
+        else {
+            throw new MessagingException("Error retrieving article headers from server: " + reply);
+        }
+    }
+
+    /**
+     * Update the message headers from an input stream.
+     *
+     * @param in     The InputStream source for the header information.
+     *
+     * @exception MessagingException
+     */
+    public void updateHeaders(InputStream in) throws MessagingException {
+        // wrap a stream around the reply data and read as headers.
+        headers = new InternetHeaders(in);
+        headersLoaded = true;
+    }
+
+
+    /**
+     * Load just the message content from the NNTP server.
+     *
+     * @exception MessagingException
+     */
+    public void loadContent() throws MessagingException {
+        if (contentLoaded) {
+            return;
+        }
+
+        NNTPReply reply = connection.sendCommand("BODY " + messageID, NNTPReply.BODY_FOLLOWS);
+
+        if (reply.getCode() == NNTPReply.BODY_FOLLOWS) {
+            try {
+                InputStream in = new StringListInputStream(reply.getData());
+                updateContent(in);
+            } catch (IOException e) {
+                throw new MessagingException("Error retrieving article body from server", e);
+            }
+        }
+        else {
+            throw new MessagingException("Error retrieving article body from server: " + reply);
+        }
+    }
+
+
+    /**
+     * Load the entire article from the NNTP server.  This updates
+     * both the headers and the content.
+     *
+     * @exception MessagingException
+     */
+    public void loadArticle() throws MessagingException {
+        // if the headers are already loaded, retrieve the content portion.
+        if (headersLoaded) {
+            loadContent();
+            return;
+        }
+
+        // we need to retrieve everything.
+        NNTPReply reply = connection.sendCommand("ARTICLE " + messageID, NNTPReply.ARTICLE_FOLLOWS);
+
+        if (reply.getCode() == NNTPReply.ARTICLE_FOLLOWS) {
+            try {
+                InputStream in = new StringListInputStream(reply.getData());
+                // update both the headers and the content.
+                updateHeaders(in);
+                updateContent(in);
+            } catch (IOException e) {
+                throw new MessagingException("Error retrieving article from server", e);
+            }
+        }
+        else {
+            throw new MessagingException("Error retrieving article from server: " + reply);
+        }
+    }
+
+
+    /**
+     * Update the article content from an input stream.
+     *
+     * @param in     The content data source.
+     *
+     * @exception MessagingException
+     */
+    public void updateContent(InputStream in) throws MessagingException {
+        try {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+            byte[] buffer = new byte[4096];
+
+            // copy the content data from the stream into a byte buffer for the content.
+            while (true) {
+                int read = in.read(buffer);
+                if (read == -1) {
+                    break;
+                }
+                out.write(buffer, 0, read);
+            }
+
+            content = out.toByteArray();
+            contentLoaded = true;
+        } catch (IOException e) {
+            throw new MessagingException("Error retrieving message body from server", e);
+        }
+    }
+
+    /**
+     * Get the server assigned messageid for the article.
+     *
+     * @return The server assigned message id.
+     */
+    public String getMessageId() {
+        return messageID;
+    }
+
+
+    /**
+     * Override of setFlags().  We need to ensure that if the SEEN
+     * flag is set or cleared, that the newsrc file correctly
+     * reflects the current state.
+     *
+     * @param flag     The flag being set.
+     * @param newvalue The new flag value.
+     *
+     * @exception MessagingException
+     */
+    public void setFlags(Flags flag, boolean newvalue) throws MessagingException {
+        // if this is the SEEN flag, make sure we shadow this in the newsrc file.
+        if (flag.contains(Flags.Flag.SEEN)) {
+            ((NNTPFolder) folder).setSeen(msgnum, newvalue);
+        }
+        // have the superclass do the real flag setting.
+        super.setFlags(flag, newvalue);
+    }
+}

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPMessage.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPMessage.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPRootFolder.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPRootFolder.java?rev=384292&view=auto
==============================================================================
--- geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPRootFolder.java (added)
+++ geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPRootFolder.java Wed Mar  8 10:04:19 2006
@@ -0,0 +1,386 @@
+/**
+ *
+ * Copyright 2003-2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.geronimo.javamail.store.nntp;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Iterator;
+
+import javax.mail.FetchProfile;
+import javax.mail.Flags;
+import javax.mail.Folder;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.MethodNotSupportedException;
+import javax.mail.Session;
+import javax.mail.Store;
+import javax.mail.URLName;
+import javax.mail.event.ConnectionEvent;
+
+import org.apache.geronimo.javamail.transport.nntp.NNTPConnection;
+import org.apache.geronimo.javamail.transport.nntp.NNTPReply;
+
+import org.apache.geronimo.javamail.store.nntp.newsrc.NNTPNewsrcGroup;
+
+import org.apache.geronimo.mail.util.SessionUtil;
+
+/**
+ * The base NNTP implementation of the javax.mail.Folder
+ * This is a base class for both the Root NNTP server and each NNTP group folder.
+ * @see javax.mail.Folder
+ *
+ * @version $Rev$
+ */
+public class NNTPRootFolder extends NNTPFolder {
+    protected static final String NNTP_LISTALL = "mail.nntp.listall";
+
+    /**
+     * Construct the NNTPRootFolder.
+     *
+     * @param store    The owning Store.
+     * @param name     The folder name (by default, this is the server host name).
+     * @param fullName The fullName to use for this server (derived from welcome string).
+     */
+	protected NNTPRootFolder(NNTPStore store, String name, String fullName) {
+		super(store);
+
+        this.name = name;
+        this.fullName = fullName;
+	}
+
+    /**
+     * List the subfolders.  For group folders, this is a meaningless
+     * so we throw a MethodNotSupportedException.
+     *
+     * @param pattern The folder pattern string.
+     *
+     * @return Never returns.
+     * @exception MessagingException
+     */
+	public synchronized Folder[] list(String pattern) throws MessagingException {
+        // the pattern specfied for javamail uses two wild card characters, "%" and "*".  The "%" matches
+        // and character except hierarchy separators.  Since we have a flag hierarchy, "%" and "*" are
+        // essentially the same.  If we convert the "%" into "*", we can just treat this as a wildmat
+        // formatted pattern and pass this on to the server rather than having to read everything and
+        // process the strings on the client side.
+
+        pattern = pattern.replace('%', '*');
+
+        // if we're not supposed to list everything, then just filter the list of subscribed groups.
+        if (SessionUtil.getBooleanProperty(NNTP_LISTALL, false)) {
+            return filterActiveGroups(pattern);
+        }
+        else {
+            return filterSubscribedGroups(pattern);
+        }
+	}
+
+    /**
+     * Retrieve the list of subscribed folders that match the given
+     * pattern string.
+     *
+     * @param pattern The pattern string used for the matching
+     *
+     * @return An array of matching folders from the subscribed list.
+     */
+    public Folder[] listSubscribed(String pattern) throws MessagingException {
+        // the pattern specfied for javamail uses two wild card characters, "%" and "*".  The "%" matches
+        // and character except hierarchy separators.  Since we have a flag hierarchy, "%" and "*" are
+        // essentially the same.  If we convert the "%" into "*", we can just treat this as a wildmat
+        // formatted pattern and pass this on to the server rather than having to read everything and
+        // process the strings on the client side.
+
+        pattern = pattern.replace('%', '*');
+
+        return filterSubscribedGroups(pattern);
+    }
+
+
+    /**
+     * Retrieve the list of matching groups from the NNTP server using
+     * the LIST ACTIVE command.  The server does the wildcard
+     * matching for us.
+     *
+     * @param pattern The pattern string (in wildmat format) used to match.
+     *
+     * @return An array of folders for the matching groups.
+     */
+    protected Folder[] filterActiveGroups(String pattern) throws MessagingException {
+        NNTPReply reply = connection.sendCommand("LIST ACTIVE " + pattern, NNTPReply.LIST_FOLLOWS);
+
+        // if the LIST ACTIVE command isn't supported,
+        if (reply.getCode() == NNTPReply.COMMAND_NOT_RECOGNIZED) {
+            // only way to list all is to retrieve all and filter.
+            return filterAllGroups(pattern);
+        }
+        else if (reply.getCode() != NNTPReply.LIST_FOLLOWS) {
+            throw new MessagingException("Error retrieving group list from NNTP server: " + reply);
+        }
+
+        // get the response back from the server and process each returned group name.
+        List groups = reply.getData();
+
+        Folder[] folders = new Folder[groups.size()];
+        for (int i = 0; i < groups.size(); i++) {
+            folders[i] = getFolder(getGroupName((String)groups.get(i)));
+        }
+        return folders;
+    }
+
+
+    /**
+     * Retrieve a list of all groups from the server and filter
+     * on the names.  Not recommended for the usenet servers, as
+     * there are over 30000 groups to process.
+     *
+     * @param pattern The pattern string used for the selection.
+     *
+     * @return The Folders for the matching groups.
+     */
+    protected Folder[] filterAllGroups(String pattern) throws MessagingException {
+        NNTPReply reply = connection.sendCommand("LIST", NNTPReply.LIST_FOLLOWS);
+
+        if (reply.getCode() != NNTPReply.LIST_FOLLOWS) {
+            throw new MessagingException("Error retrieving group list from NNTP server: " + reply);
+        }
+
+        // get the response back from the server and process each returned group name.
+        List groups = reply.getData();
+
+        WildmatMatcher matcher = new WildmatMatcher(pattern);
+
+        List folders = new ArrayList();
+        for (int i = 0; i < groups.size(); i++) {
+            String name = getGroupName((String)groups.get(i));
+            // does this match our pattern?  Add to the list
+            if (matcher.matches(name)) {
+                folders.add(getFolder(name));
+            }
+        }
+        return (Folder [])folders.toArray(new Folder[0]);
+    }
+
+
+    /**
+     * Return the set of groups from the newsrc subscribed groups
+     * list that match a given filter.
+     *
+     * @param pattern The selection pattern.
+     *
+     * @return The Folders for the matching groups.
+     */
+    protected Folder[] filterSubscribedGroups(String pattern) throws MessagingException {
+        Iterator groups = ((NNTPStore)store).getNewsrcGroups();
+
+        WildmatMatcher matcher = new WildmatMatcher(pattern);
+
+        List folders = new ArrayList();
+        while (groups.hasNext()) {
+            NNTPNewsrcGroup group = (NNTPNewsrcGroup)groups.next();
+            if (group.isSubscribed()) {
+                // does this match our pattern?  Add to the list
+                if (matcher.matches(group.getName())) {
+                    folders.add(getFolder(group.getName()));
+                }
+            }
+        }
+        return (Folder [])folders.toArray(new Folder[0]);
+    }
+
+
+    /**
+     * Utility method for extracting a name from a group list
+     * response.
+     *
+     * @param response The response string.
+     *
+     * @return The group name.
+     */
+    protected String getGroupName(String response) {
+        int blank = response.indexOf(' ');
+        return response.substring(0, blank).trim();
+    }
+
+
+    /**
+     * Return whether this folder can hold just messages or also
+     * subfolders.  Only the root folder can hold other folders,
+     * so it will need to override.
+     *
+     * @return Always returns Folder.HOLDS_FOLDERS.
+     * @exception MessagingException
+     */
+	public int getType() throws MessagingException {
+		return HOLDS_FOLDERS;
+	}
+
+
+    /**
+     * Get a new folder from the root folder.  This creates a new
+     * folder, which might not actually exist on the server.  If the
+     * folder doesn't exist, an error will occur on folder open.
+     *
+     * @param name   The name of the requested folder.
+     *
+     * @return A new folder object for this folder.
+     * @exception MessagingException
+     */
+	public Folder getFolder(String name) throws MessagingException {
+        // create a new group folder and return
+        return new NNTPGroupFolder(this, (NNTPStore)store, name, ((NNTPStore)store).getNewsrcGroup(name));
+	}
+
+    /**
+     * Utility class to do Wildmat pattern matching on folder names.
+     */
+    class WildmatMatcher {
+        // middle match sections...because these are separated by wildcards, if they appear in
+        // sequence in the string, it is a match.
+        List matchSections = new ArrayList();
+        // just a "*" match, so everything is true
+        boolean matchAny = false;
+        // no wildcards, so this must be an exact match.
+        String exactMatch = null;
+
+        // a leading section which must be at the beginning
+        String firstSection = null;
+        // a trailing section which must be at the end of the string.
+        String lastSection = null;
+
+        /**
+         * Create a wildmat pattern matcher.
+         *
+         * @param pattern The wildmat pattern to apply to string matches.
+         */
+        public WildmatMatcher(String pattern) {
+            int section = 0;
+
+            // handle the easy cases first
+
+            // single wild card?
+            if (pattern.equals("*")) {
+                matchAny = true;
+                return;
+            }
+
+            // find the first wild card
+            int wildcard = pattern.indexOf('*');
+
+            // no wild card at all?
+            if (wildcard == -1) {
+                exactMatch = pattern;
+                return;
+            }
+
+            // pattern not begin with a wildcard?  We need to pull off the leading section
+            if (!pattern.startsWith("*")) {
+                firstSection = pattern.substring(0, wildcard);
+                section = wildcard + 1;
+                // this could be "yada*", so we could be done.
+                if (section >= pattern.length()) {
+                    return;
+                }
+            }
+
+            // now parse off the middle sections, making sure to handle the end condition correctly.
+            while (section < pattern.length()) {
+                // find the next wildcard position
+                wildcard = pattern.indexOf('*', section);
+                if (wildcard == -1) {
+                    // not found, we're at the end of the pattern.  We need to match on the end.
+                    lastSection = pattern.substring(section);
+                    return;
+                }
+                // we could have a null section, which we'll just ignore.
+                else if (wildcard == section) {
+                    // step over the wild card
+                    section++;
+                }
+                else {
+                    // pluck off the next section
+                    matchSections.add(pattern.substring(section, wildcard));
+                    // step over the wild card character and check if we've reached the end.
+                    section = wildcard + 1;
+                }
+            }
+        }
+
+        /**
+         * Test if a name string matches to parsed wildmat pattern.
+         *
+         * @param name   The name to test.
+         *
+         * @return true if the string matches the pattern, false otherwise.
+         */
+        public boolean matches(String name) {
+
+            // handle the easy cases first
+
+            // full wildcard?  Always matches
+            if (matchAny) {
+                return true;
+            }
+
+            // required exact matches are easy.
+            if (exactMatch != null) {
+                return exactMatch.equals(name);
+            }
+
+            int span = 0;
+
+            // must match the beginning?
+            if (firstSection != null) {
+                // if it doesn't start with that, it can't be true.
+                if (!name.startsWith(firstSection)) {
+                    return false;
+                }
+
+                // we do all additional matching activity from here.
+                span = firstSection.length();
+            }
+
+            // scan for each of the sections along the string
+            for (int i = 1; i < matchSections.size(); i++) {
+                // if a section is not found, this is false
+
+                String nextMatch = (String)matchSections.get(i);
+                int nextLocation = name.indexOf(nextMatch, span);
+                if (nextLocation == -1) {
+                    return false;
+                }
+                // step over that one
+                span = nextMatch.length() + nextLocation;
+            }
+
+            // we've matched everything up to this point, now check to see if need an end match
+            if (lastSection != null) {
+                // we need to have at least the number of characters of the end string left, else this fails.
+                if (name.length() - span < lastSection.length()) {
+                    return false;
+                }
+
+                // ok, make sure we end with this string
+                return name.endsWith(lastSection);
+            }
+
+            // no falsies, this must be the truth.
+            return true;
+        }
+    }
+}
+

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPRootFolder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPRootFolder.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPStore.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPStore.java?rev=384292&view=auto
==============================================================================
--- geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPStore.java (added)
+++ geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPStore.java Wed Mar  8 10:04:19 2006
@@ -0,0 +1,260 @@
+/**
+ *
+ * Copyright 2003-2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+
+package org.apache.geronimo.javamail.store.nntp;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+
+import java.util.Iterator;
+
+import javax.mail.AuthenticationFailedException;
+import javax.mail.Folder;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.Store;
+import javax.mail.URLName;
+
+import org.apache.geronimo.javamail.transport.nntp.NNTPConnection;
+import org.apache.geronimo.javamail.transport.nntp.NNTPReply;
+
+import org.apache.geronimo.javamail.store.nntp.newsrc.NNTPNewsrc;
+import org.apache.geronimo.javamail.store.nntp.newsrc.NNTPNewsrcFile;
+import org.apache.geronimo.javamail.store.nntp.newsrc.NNTPNewsrcGroup;
+import org.apache.geronimo.mail.util.SessionUtil;
+
+/**
+ * NNTP implementation of javax.mail.Store
+ * POP protocol spec is implemented in
+ * org.apache.geronimo.javamail.store.pop3.NNTPConnection
+ *
+ * @version $Rev$ $Date$
+ */
+
+public class NNTPStore extends Store{
+
+    protected static final String NNTP_AUTH = "mail.nntp.auth";
+    protected static final String NNTP_PORT = "mail.nntp.port";
+    protected static final String NNTP_NEWSRC = "mail.nntp.newsrc";
+
+    protected static final int DEFAULT_NNTP_PORT = 119;
+
+    // the active connection object.
+	protected NNTPConnection connection;
+    // the newsrc file where we store subscriptions and seen message markers.
+    protected NNTPNewsrc newsrc;
+    // the root folder
+    protected NNTPRootFolder root;
+    // our session provided debug output stream.
+    protected PrintStream debugStream;
+
+
+    /**
+     * Construct an NNTPStore item.  This will load the .newsrc file
+     * associated with the server.
+     *
+     * @param session The owning javamail Session.
+     * @param urlName The Store urlName, which can contain server target information.
+     */
+	public NNTPStore(Session session, URLName urlName) {
+		super(session,urlName);
+
+        // get our debug output.
+        debugStream = session.getDebugOut();
+
+	}
+
+
+	/**
+	 * @see javax.mail.Store#getDefaultFolder()
+	 *
+	 * This returns a root folder object for all of the news groups.
+	 */
+	public Folder getDefaultFolder() throws MessagingException {
+		checkConnectionStatus();
+        if (root == null) {
+            return new NNTPRootFolder(this, connection.getHost(), connection.getWelcomeString());
+        }
+        return root;
+	}
+
+	/**
+	 * @see javax.mail.Store#getFolder(java.lang.String)
+	 */
+	public Folder getFolder(String name) throws MessagingException {
+        return getDefaultFolder().getFolder(name);
+	}
+
+    /**
+
+	 * @see javax.mail.Store#getFolder(javax.mail.URLName)
+	 */
+	public Folder getFolder(URLName url) throws MessagingException {
+        return getDefaultFolder().getFolder(url.getFile());
+	}
+
+
+	/**
+	 * @see javax.mail.Service#protocolConnect(java.lang.String, int, java.lang.String, java.lang.String)
+	 */
+	protected synchronized boolean protocolConnect(String host, int port, String username, String password) throws MessagingException {
+        if (debug) {
+            debugOut("Connecting to server " + host + ":" + port + " for user " + username);
+        }
+
+        // first check to see if we need to authenticate.  If we need this, then we must have a username and
+        // password specified.  Failing this may result in a user prompt to collect the information.
+        boolean mustAuthenticate = SessionUtil.getBooleanProperty(session, NNTP_AUTH, false);
+
+        // if we need to authenticate, and we don't have both a userid and password, then we fail this
+        // immediately.  The Service.connect() method will try to obtain the user information and retry the
+        // connection one time.
+        if (mustAuthenticate && (username == null || password == null)) {
+            return false;
+        }
+
+
+        // if the port is defaulted, then see if we have something configured in the session.
+        // if not configured, we just use the default default.
+        if (port == -1) {
+            // check for a property and fall back on the default if it's not set.
+            port = SessionUtil.getIntProperty(session, NNTP_PORT, DEFAULT_NNTP_PORT);
+        }
+
+
+        // create socket and connect to server.
+        connection = new NNTPConnection(session, host, port, username, password, debug);
+        connection.connect();
+
+        // see if we have a newsrc file location specified
+        String newsrcFile = session.getProperty(NNTP_NEWSRC);
+
+        File source = null;
+
+        // not given as a property?  Then look for a file in user.home
+        if (newsrcFile != null) {
+            source = new File(newsrcFile);
+        }
+        else {
+            // ok, look for a file in the user.home directory.  If possible, we'll try for a file
+            // with the hostname appended.
+            String home = SessionUtil.getProperty("user.home");
+
+            // try for a host-specific file first.  If not found, use (and potentially create) a generic
+            // .newsrc file.
+            newsrcFile = ".newsrc-" + host;
+            source = new File(home, newsrcFile);
+            if (!source.exists()) {
+                source = new File(home, ".newsrc");
+            }
+        }
+
+        // now create a newsrc read and load the file.
+        newsrc = new NNTPNewsrcFile(source);
+        newsrc.load();
+
+        // we're going to return success here, but in truth, the server may end up asking for our
+        // bonafides at any time, and we'll be expected to authenticate then.
+        return true;
+	}
+
+
+	/**
+	 * @see javax.mail.Service#close()
+	 */
+	public void close() throws MessagingException{
+		// This is done to ensure proper event notification.
+		super.close();
+        // persist the newsrc file, if possible
+        newsrc.close();
+        connection.close();
+        connection = null;
+	}
+
+	private void checkConnectionStatus() throws MessagingException {
+		if (!this.isConnected()){
+		    throw new MessagingException("Not connected ");
+	    }
+	}
+
+    /**
+     * Internal debug output routine.
+     *
+     * @param value  The string value to output.
+     */
+    void debugOut(String message) {
+        debugStream.println("NNTPTransport DEBUG: " + message);
+    }
+
+    /**
+     * Internal debugging routine for reporting exceptions.
+     *
+     * @param message A message associated with the exception context.
+     * @param e       The received exception.
+     */
+    void debugOut(String message, Throwable e) {
+        debugOut("Received exception -> " + message);
+        debugOut("Exception message -> " + e.getMessage());
+        e.printStackTrace(debugStream);
+    }
+
+
+    /**
+     * Retrieve the server connection created by this store.
+     *
+     * @return The active connection object.
+     */
+    NNTPConnection getConnection() {
+        return connection;
+    }
+
+
+    /**
+     * Retrieve the Session object this Store is operating under.
+     *
+     * @return The attached Session instance.
+     */
+    Session getSession() {
+        return session;
+    }
+
+    /**
+     * Retrieve all of the groups we nave persistent store information
+     * about.
+     *
+     * @return The set of groups contained in the newsrc file.
+     */
+    Iterator getNewsrcGroups() {
+        return newsrc.getGroups();
+    }
+
+    /**
+     * Retrieve the newsrc group information for a named group.  If
+     * the file does not currently include this group, an unsubscribed
+     * group will be added to the file.
+     *
+     * @param name   The name of the target group.
+     *
+     * @return The NNTPNewsrcGroup item corresponding to this name.
+     */
+    NNTPNewsrcGroup getNewsrcGroup(String name) {
+        return newsrc.getGroup(name);
+    }
+
+}

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPStore.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/NNTPStore.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrc.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrc.java?rev=384292&view=auto
==============================================================================
--- geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrc.java (added)
+++ geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrc.java Wed Mar  8 10:04:19 2006
@@ -0,0 +1,182 @@
+/**
+ *
+ * Copyright 2003-2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.geronimo.javamail.store.nntp.newsrc;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+
+/**
+ * Base class implementation of a standard news reader news rc
+ * file.  This is used to track newsgroup subscriptions and
+ * SEEN flags for articles.  This is an abstract class designed
+ * for subclasses to bridge to the physical store type used for
+ * the newsgroup information.
+ */
+public abstract class NNTPNewsrc {
+
+    // the group information we've read from the news rc file.
+    Map groups = new HashMap();
+    // flag to let us know of we need to persist the newsrc file on close.
+    boolean dirty = false;
+
+    /**
+     * Base class constructor for NNTPNewsrc items.  Subclasses
+     * provide their own domain-specific intialization.
+     */
+    protected NNTPNewsrc() {
+    }
+
+    /**
+     * Load the data from the newsrc file and parse into an instore
+     * group database.
+     */
+    public void load() {
+        BufferedReader in = null;
+
+        try {
+            in = getInputReader();
+
+            String line = in.readLine();
+
+            while (line != null) {
+                // parse the line...this returns null if it's something unrecognized.
+                NNTPNewsrcGroup group = NNTPNewsrcGroup.parse(this, line);
+                // if it parsed ok, add it to the group list, and potentially to the subscribed list.
+                if (group != null) {
+                    groups.put(group.getName(), group);
+                }
+
+                line = in.readLine();
+            }
+
+            in.close();
+        } catch (IOException e) {
+            // an IOException may mean that the file just doesn't exist, which is fine.  We'll ignore and
+            // proceed with the information we have.
+        }
+        finally {
+            if (in != null) {
+                try {
+                    in.close();
+                } catch (IOException e) {
+                    // ignore
+                }
+            }
+        }
+    }
+
+    /**
+     * Save the newsrc file data back to the original source file.
+     *
+     * @exception IOException
+     */
+    public void save() throws IOException {
+        Writer out = getOutputWriter();
+
+        Iterator i = groups.values().iterator();
+
+        while (i.hasNext()) {
+            NNTPNewsrcGroup group = (NNTPNewsrcGroup)i.next();
+            group.save(out);
+        }
+
+        out.close();
+    }
+
+
+    /**
+     * Abstract open method intended for sub class initialization.  The
+     * subclass is responsible for creating the BufferedReaded used
+     * to read the .newsrc file.
+     *
+     * @return A BufferedReader for reading the .newsrc file.
+     * @exception IOException
+     */
+    abstract public BufferedReader getInputReader() throws IOException;
+    /**
+     * Abstract open for output method intended for subclass implementation.
+     * The subclasses are reponsible for opening the output stream
+     * and creating an appropriate Writer for saving the .newsrc file.
+     *
+     * @return A Writer target at the .newsrc file save location.
+     * @exception IOException
+     */
+    abstract public Writer getOutputWriter() throws IOException;
+
+
+    /**
+     * Retrieve the newsrc group information for a named group.  If
+     * the file does not currently include this group, an unsubscribed
+     * group will be added to the file.
+     *
+     * @param name   The name of the target group.
+     *
+     * @return The NNTPNewsrcGroup item corresponding to this name.
+     */
+    public NNTPNewsrcGroup getGroup(String name) {
+        NNTPNewsrcGroup group = (NNTPNewsrcGroup)groups.get(name);
+        // if we don't know about this, create a new one and add to the list.  This
+        // will be an unsubscribed one.
+        if (group == null) {
+            group = new NNTPNewsrcGroup(this, name, null, false);
+            groups.put(name, group);
+            // we've added a group, so we need to resave
+            dirty = true;
+        }
+        return group;
+    }
+
+    /**
+     * Mark this newsrc database as dirty.
+     */
+    public void setDirty() {
+        dirty = true;
+    }
+
+
+    /**
+     * Close the newsrc file, persisting it back to disk if the
+     * file has changed.
+     */
+    public void close() {
+        if (dirty) {
+            try {
+                save();
+            } catch (IOException e) {
+                // ignore
+            }
+        }
+    }
+
+
+    /**
+     * Retrieve the current set of loaded groups.
+     *
+     * @return An iterator for traversing the group set.
+     */
+    public Iterator getGroups() {
+        return groups.values().iterator();
+    }
+}

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrc.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrc.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcFile.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcFile.java?rev=384292&view=auto
==============================================================================
--- geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcFile.java (added)
+++ geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcFile.java Wed Mar  8 10:04:19 2006
@@ -0,0 +1,66 @@
+/**
+ *
+ * Copyright 2003-2005 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.geronimo.javamail.store.nntp.newsrc;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+
+public class NNTPNewsrcFile extends NNTPNewsrc {
+    // source for the file data
+    File source;
+
+    /**
+     * Construct a NNTPNewsrc object that is targetted at a
+     * file-based backing store.
+     *
+     * @param source The source File for the .newsrc data.
+     */
+    public NNTPNewsrcFile(File source) {
+        this.source = source;
+    }
+
+    /**
+     * Retrieve an input reader for loading the newsrc file.
+     *
+     * @return A BufferedReader object for reading from the newsrc file.
+     * @exception IOException
+     */
+    public BufferedReader getInputReader() throws IOException {
+        return new BufferedReader(new InputStreamReader(new FileInputStream(source)));
+    }
+
+    /**
+     * Obtain a writer for saving a newsrc file.
+     *
+     * @return The output writer targetted to the newsrc file.
+     * @exception IOException
+     */
+    public Writer getOutputWriter() throws IOException {
+        // open this for overwriting
+        return new OutputStreamWriter(new FileOutputStream(source, false));
+    }
+}
+

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcFile.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/trunk/modules/javamail-transport/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcFile.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date



Mime
View raw message