You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by ri...@apache.org on 2006/06/14 12:18:55 UTC
svn commit: r414173 [2/7] - in /geronimo/javamail/trunk: ./
javamail-provider-1.3/ javamail-provider-1.3/src/
javamail-provider-1.3/src/java/ javamail-provider-1.3/src/java/org/
javamail-provider-1.3/src/java/org/apache/ javamail-provider-1.3/src/java/...
Added: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPGroupFolder.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPGroupFolder.java?rev=414173&view=auto
==============================================================================
--- geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPGroupFolder.java (added)
+++ geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPGroupFolder.java Wed Jun 14 03:18:51 2006
@@ -0,0 +1,384 @@
+/**
+ *
+ * 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.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.mail.FetchProfile;
+import javax.mail.FolderNotFoundException;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+
+import org.apache.geronimo.javamail.store.nntp.newsrc.NNTPNewsrcGroup;
+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/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPGroupFolder.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPGroupFolder.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPGroupFolder.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPMessage.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPMessage.java?rev=414173&view=auto
==============================================================================
--- geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPMessage.java (added)
+++ geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPMessage.java Wed Jun 14 03:18:51 2006
@@ -0,0 +1,375 @@
+/**
+ *
+ * Copyright 2006 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.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+
+import javax.mail.Flags;
+import javax.mail.IllegalWriteException;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+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);
+ }
+
+ // the following are overrides for header modification methods. These
+ // messages are read only,
+ // so the headers cannot be modified.
+ public void addHeader(String name, String value) throws MessagingException {
+ throw new IllegalWriteException("NNTP messages are read-only");
+ }
+
+ public void setHeader(String name, String value) throws MessagingException {
+ throw new IllegalWriteException("NNTP messages are read-only");
+ }
+
+ public void removeHeader(String name) throws MessagingException {
+ throw new IllegalWriteException("NNTP messages are read-only");
+ }
+
+ public void addHeaderLine(String line) throws MessagingException {
+ throw new IllegalWriteException("IMAP messages are read-only");
+ }
+
+ /**
+ * 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/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPMessage.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPMessage.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPMessage.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPRootFolder.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPRootFolder.java?rev=414173&view=auto
==============================================================================
--- geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPRootFolder.java (added)
+++ geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPRootFolder.java Wed Jun 14 03:18:51 2006
@@ -0,0 +1,397 @@
+/**
+ *
+ * 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.Iterator;
+import java.util.List;
+
+import javax.mail.Folder;
+import javax.mail.MessagingException;
+
+import org.apache.geronimo.javamail.store.nntp.newsrc.NNTPNewsrcGroup;
+import org.apache.geronimo.javamail.transport.nntp.NNTPReply;
+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/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPRootFolder.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPRootFolder.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPRootFolder.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPStore.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPStore.java?rev=414173&view=auto
==============================================================================
--- geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPStore.java (added)
+++ geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPStore.java Wed Jun 14 03:18:51 2006
@@ -0,0 +1,343 @@
+/**
+ *
+ * Copyright 2006 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.PrintStream;
+import java.util.Iterator;
+
+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.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.javamail.transport.nntp.NNTPConnection;
+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 = "auth";
+
+ protected static final String NNTP_PORT = "port";
+
+ protected static final String NNTP_NEWSRC = "newsrc";
+
+ protected static final String protocol = "nntp";
+
+ 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 = getBooleanProperty(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 = getIntProperty(NNTP_PORT, DEFAULT_NNTP_PORT);
+ }
+
+ // create socket and connect to server.
+ connection = new NNTPConnection(protocol, session, host, port, username, password, debug);
+ connection.connect();
+
+ // see if we have a newsrc file location specified
+ String newsrcFile = 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);
+ }
+
+ /**
+ * Get a property associated with this mail protocol.
+ *
+ * @param name
+ * The name of the property.
+ *
+ * @return The property value (returns null if the property has not been
+ * set).
+ */
+ String getProperty(String name) {
+ // the name we're given is the least qualified part of the name. We
+ // construct the full property name
+ // using the protocol (either "nntp" or "nntp-post").
+ String fullName = "mail." + protocol + "." + name;
+ return session.getProperty(fullName);
+ }
+
+ /**
+ * Get a property associated with this mail session. Returns the provided
+ * default if it doesn't exist.
+ *
+ * @param name
+ * The name of the property.
+ * @param defaultValue
+ * The default value to return if the property doesn't exist.
+ *
+ * @return The property value (returns defaultValue if the property has not
+ * been set).
+ */
+ String getProperty(String name, String defaultValue) {
+ // the name we're given is the least qualified part of the name. We
+ // construct the full property name
+ // using the protocol (either "nntp" or "nntp-post").
+ String fullName = "mail." + protocol + "." + name;
+ return SessionUtil.getProperty(session, fullName, defaultValue);
+ }
+
+ /**
+ * Get a property associated with this mail session as an integer value.
+ * Returns the default value if the property doesn't exist or it doesn't
+ * have a valid int value.
+ *
+ * @param name
+ * The name of the property.
+ * @param defaultValue
+ * The default value to return if the property doesn't exist.
+ *
+ * @return The property value converted to an int.
+ */
+ int getIntProperty(String name, int defaultValue) {
+ // the name we're given is the least qualified part of the name. We
+ // construct the full property name
+ // using the protocol (either "nntp" or "nntp-post").
+ String fullName = "mail." + protocol + "." + name;
+ return SessionUtil.getIntProperty(session, fullName, defaultValue);
+ }
+
+ /**
+ * Get a property associated with this mail session as an boolean value.
+ * Returns the default value if the property doesn't exist or it doesn't
+ * have a valid int value.
+ *
+ * @param name
+ * The name of the property.
+ * @param defaultValue
+ * The default value to return if the property doesn't exist.
+ *
+ * @return The property value converted to a boolean
+ */
+ boolean getBooleanProperty(String name, boolean defaultValue) {
+ // the name we're given is the least qualified part of the name. We
+ // construct the full property name
+ // using the protocol (either "nntp" or "nntp-post").
+ String fullName = "mail." + protocol + "." + name;
+ return SessionUtil.getBooleanProperty(session, fullName, defaultValue);
+ }
+}
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPStore.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPStore.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/NNTPStore.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrc.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrc.java?rev=414173&view=auto
==============================================================================
--- geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrc.java (added)
+++ geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrc.java Wed Jun 14 03:18:51 2006
@@ -0,0 +1,180 @@
+/**
+ *
+ * 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.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/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrc.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrc.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrc.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcFile.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcFile.java?rev=414173&view=auto
==============================================================================
--- geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcFile.java (added)
+++ geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcFile.java Wed Jun 14 03:18:51 2006
@@ -0,0 +1,64 @@
+/**
+ *
+ * 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.InputStreamReader;
+import java.io.OutputStreamWriter;
+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/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcFile.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcFile.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcFile.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcGroup.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcGroup.java?rev=414173&view=auto
==============================================================================
--- geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcGroup.java (added)
+++ geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcGroup.java Wed Jun 14 03:18:51 2006
@@ -0,0 +1,183 @@
+/**
+ *
+ * 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.IOException;
+import java.io.Writer;
+
+public class NNTPNewsrcGroup {
+ // the newsrc database we're part of
+ NNTPNewsrc newsrc;
+
+ // the name of the group
+ protected String name;
+
+ // the subscription flage
+ protected boolean subscribed;
+
+ // the range of already seen articles.
+ protected RangeList ranges;
+
+ /**
+ * Construct a NNTPNewsrcGroup item associated with a given .newsrc
+ * database.
+ *
+ * @param newsrc
+ * The owning .newsrc database.
+ * @param line
+ * The .newsrc range entries in .newsrc format. These ranges are
+ * parsed to create a set of seen flags.
+ *
+ * @return A created NNTPNewsrcGroup item.
+ */
+ public static NNTPNewsrcGroup parse(NNTPNewsrc newsrc, String line) {
+ String groupName = null;
+ String ranges = null;
+
+ // subscribed lines have a ':' marker acting as a delimiter
+ int marker = line.indexOf(':');
+
+ if (marker != -1) {
+ groupName = line.substring(0, marker);
+ ranges = line.substring(marker + 1);
+ return new NNTPNewsrcGroup(newsrc, groupName, ranges, true);
+ }
+
+ // now check for an unsubscribed group
+ marker = line.indexOf('!');
+
+ if (marker != -1) {
+ groupName = line.substring(0, marker);
+ ranges = line.substring(marker + 1);
+ return new NNTPNewsrcGroup(newsrc, groupName, ranges, false);
+ }
+
+ // must be a comment line
+ return null;
+ }
+
+ /**
+ * Construct a .newsrc group item.
+ *
+ * @param newsrc
+ * The owning newsrc database.
+ * @param name
+ * The group name.
+ * @param newsrcRanges
+ * The initial set of seen ranges for the group (may be null).
+ * @param subscribed
+ * The initial group subscription state.
+ */
+ public NNTPNewsrcGroup(NNTPNewsrc newsrc, String name, String newsrcRanges, boolean subscribed) {
+ this.newsrc = newsrc;
+ this.name = name;
+ this.subscribed = subscribed;
+ this.ranges = new RangeList(newsrcRanges);
+ }
+
+ /**
+ * Get the group name.
+ *
+ * @return The String name of the group.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Get the newsrc subscribed status for an article.
+ *
+ * @return The current subscription flag.
+ */
+ public boolean isSubscribed() {
+ return subscribed;
+ }
+
+ /**
+ * Set the subscription status for an article.
+ *
+ * @param flag
+ * The new subscription value.
+ */
+ public void setSubscribed(boolean flag) {
+ // we don't blindly set this to the new value since we only want to
+ // resave the newsrc file if
+ // something changes.
+ if (flag && !subscribed) {
+ subscribed = true;
+ newsrc.setDirty();
+ } else if (!flag && subscribed) {
+ subscribed = false;
+ newsrc.setDirty();
+ }
+ }
+
+ /**
+ * Test if an article has been seen yet.
+ *
+ * @param article
+ * The target article.
+ *
+ * @return The seen mark for the article.
+ */
+ public boolean isArticleSeen(int article) {
+ return ranges.isMarked(article);
+ }
+
+ /**
+ * Mark an article as seen.
+ *
+ * @param article
+ * The target article number.
+ */
+ public void markArticleSeen(int article) {
+ ranges.setMarked(article);
+ if (ranges.isDirty()) {
+ newsrc.setDirty();
+ }
+ }
+
+ /**
+ * Mark an article as unseen.
+ *
+ * @param article
+ * The target article number.
+ */
+ public void markArticleUnseen(int article) {
+ ranges.setUnmarked(article);
+ if (ranges.isDirty()) {
+ newsrc.setDirty();
+ }
+ }
+
+ /**
+ * Save this group definition to a .newsrc file.
+ *
+ * @param out
+ * The output writer to send the information to.
+ *
+ * @exception IOException
+ */
+ public void save(Writer out) throws IOException {
+ out.write(name);
+ out.write(subscribed ? ": " : "! ");
+ ranges.save(out);
+ // put a terminating line end
+ out.write("\r\n");
+ }
+}
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcGroup.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcGroup.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/NNTPNewsrcGroup.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/Range.java
URL: http://svn.apache.org/viewvc/geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/Range.java?rev=414173&view=auto
==============================================================================
--- geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/Range.java (added)
+++ geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/Range.java Wed Jun 14 03:18:51 2006
@@ -0,0 +1,316 @@
+/**
+ *
+ * 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.IOException;
+import java.io.Writer;
+
+/**
+ * Represent a single Range in a newsrc file. A Range can be either a single
+ * number (start == end) or a span of article numbers.
+ */
+public class Range {
+ // the low end of the range
+ int start;
+
+ // the high end of the range (start and end are inclusive);
+ int end;
+
+ /**
+ * Construct a Range item for a single digit range.
+ *
+ * @param spot
+ * The location of the singleton.
+ */
+ public Range(int spot) {
+ this(spot, spot);
+ }
+
+ /**
+ * Construct a Range item.
+ *
+ * @param start
+ * The starting point of the Range.
+ * @param end
+ * The Range end point (which may be equal to the starting
+ * point).
+ */
+ public Range(int start, int end) {
+ this.start = start;
+ this.end = end;
+ }
+
+ /**
+ * Parse a section of a .newsrc range string into a single Range item. The
+ * range is either a single number, or a pair of numbers separated by a
+ * hyphen.
+ *
+ * @param range
+ * The range string.
+ *
+ * @return A constructed Range item, or null if there is a parsing error.
+ */
+ static public Range parse(String range) {
+ // a range from a newsrc file is either a single number or in the format
+ // 'nnnn-mmmm'. We need
+ // to figure out which type this is.
+ int marker = range.indexOf('-');
+
+ try {
+ if (marker != -1) {
+ String rangeStart = range.substring(0, marker).trim();
+ String rangeEnd = range.substring(marker + 1).trim();
+
+ int start = Integer.parseInt(rangeStart);
+ int end = Integer.parseInt(rangeEnd);
+
+ if (start >= 0 && end >= 0) {
+ return new Range(start, end);
+ }
+ } else {
+ // use the entire token
+ int start = Integer.parseInt(range);
+ // and start and the end are the same
+ return new Range(start, start);
+
+ }
+ } catch (NumberFormatException e) {
+ }
+ // return null for any bad values
+ return null;
+ }
+
+ /**
+ * Get the starting point for the Range.
+ *
+ * @return The beginning of the mark range.
+ */
+ public int getStart() {
+ return start;
+ }
+
+ /**
+ * Set the starting point for a Range.
+ *
+ * @param start
+ * The new start value.
+ */
+ public void setStart(int start) {
+ this.start = start;
+ }
+
+ /**
+ * Get the ending point for the Range.
+ *
+ * @return The end of the mark range.
+ */
+ public int getEnd() {
+ return end;
+ }
+
+ /**
+ * Set the ending point for a Range.
+ *
+ * @param end
+ * The new end value.
+ */
+ public void setEnd(int end) {
+ this.end = end;
+ }
+
+ /**
+ * Test if a range contains a point value.
+ *
+ * @param target
+ * The article location to test.
+ *
+ * @return True if the target is between the start and end values,
+ * inclusive.
+ */
+ public boolean contains(int target) {
+ return target >= start && target <= end;
+ }
+
+ /**
+ * Test if one range is completely contained within another Range.
+ *
+ * @param other
+ * The other test range.
+ *
+ * @return true if the other start and end points are contained within this
+ * range.
+ */
+ public boolean contains(Range other) {
+ return contains(other.getStart()) && contains(other.getEnd());
+ }
+
+ /**
+ * Tests if two ranges overlap
+ *
+ * @param other
+ * The other test range.
+ *
+ * @return true if the start or end points of either range are contained
+ * within the range of the other.
+ */
+ public boolean overlaps(Range other) {
+ return other.contains(start) || other.contains(end) || contains(other.getStart()) || contains(other.getEnd());
+ }
+
+ /**
+ * Test if two ranges exactly abutt each other.
+ *
+ * @param other
+ * The other Range to test.
+ *
+ * @return true if the end of one range abutts the start of the other range.
+ */
+ public boolean abutts(Range other) {
+ return other.getStart() == end + 1 || other.getEnd() == start - 1;
+ }
+
+ /**
+ * Tests if a single point abutts either the start or end of this Range.
+ *
+ * @param article
+ * The point to test.
+ *
+ * @return true if test point is equal to start - 1 or end + 1.
+ */
+ public boolean abutts(int article) {
+ return article == start - 1 || article == end + 1;
+ }
+
+ /**
+ * Test if a point is below the test Range.
+ *
+ * @param article
+ * The point to test.
+ *
+ * @return true if the entire range is less than the test point.
+ */
+ public boolean lessThan(int article) {
+ return end < article;
+ }
+
+ /**
+ * Test if another Range is less than this Range.
+ *
+ * @param other
+ * The other Range to test.
+ *
+ * @return true if the other Range lies completely below this Range.
+ */
+ public boolean lessThan(Range other) {
+ return end < other.start;
+ }
+
+ /**
+ * Test if a point is above the test Range.
+ *
+ * @param article
+ * The point to test.
+ *
+ * @return true if the entire range is greater than the test point.
+ */
+ public boolean greaterThan(int article) {
+ return start > article;
+ }
+
+ /**
+ * Test if another Range is greater than this Range.
+ *
+ * @param other
+ * The other Range to test.
+ *
+ * @return true if the other Range lies completely below this Range.
+ */
+ public boolean greaterThan(Range other) {
+ return start > other.end;
+ }
+
+ /**
+ * Merge another Range into this one. Merging will increase the bounds of
+ * this Range to encompass the entire span of the two. If the Ranges do not
+ * overlap, the newly created range will include the gap between the two.
+ *
+ * @param other
+ * The Range to merge.
+ */
+ public void merge(Range other) {
+ if (other.start < start) {
+ start = other.start;
+ }
+
+ if (other.end > end) {
+ end = other.end;
+ }
+ }
+
+ /**
+ * Split a range at a given split point. Splitting will truncate at the
+ * split location - 1 and return a new range beginning at location + 1; This
+ * code assumes that the split location is at neither end poing.
+ *
+ * @param location
+ * The split location. Location must be in the range start <
+ * location < end.
+ *
+ * @return A new Range object for the split portion of the range.
+ */
+ public Range split(int location) {
+ int newEnd = end;
+
+ end = location - 1;
+
+ return new Range(location + 1, newEnd);
+ }
+
+ /**
+ * Save an individual range element to a newsrc file. The range is expressed
+ * either as a single number, or a hypenated pair of numbers.
+ *
+ * @param out
+ * The output writer used to save the data.
+ *
+ * @exception IOException
+ */
+ public void save(Writer out) throws IOException {
+ // do we have a single data point range?
+ if (start == end) {
+ out.write(Integer.toString(start));
+ } else {
+ out.write(Integer.toString(start));
+ out.write("-");
+ out.write(Integer.toString(end));
+ }
+ }
+
+ /**
+ * Convert a Range into String form. Used mostly for debugging.
+ *
+ * @return The String representation of the Range.
+ */
+ public String toString() {
+ if (start == end) {
+ return Integer.toString(start);
+ } else {
+ return Integer.toString(start) + "-" + Integer.toString(end);
+ }
+ }
+}
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/Range.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/Range.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/javamail/trunk/javamail-provider-1.3/src/java/org/apache/geronimo/javamail/store/nntp/newsrc/Range.java
------------------------------------------------------------------------------
svn:mime-type = text/plain