pjs/grendel/storage/NewsStore.java

299 строки
7.8 KiB
Java

/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is the Grendel mail/news client.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1997
* Netscape Communications Corporation. All Rights Reserved.
*
* Created: Jamie Zawinski <jwz@netscape.com>, 20 Nov 1997.
*/
package grendel.storage;
import calypso.util.Assert;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.awt.Component;
import java.net.URL;
import java.net.UnknownHostException;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.URLName;
//import javax.mail.event.ConnectionEvent;
import javax.mail.event.StoreEvent;
import grendel.util.Constants;
/** Store for News (NNTP) folders.
<p>
This class really shouldn't be public, but I haven't figured out how to
tie into javamail's Session class properly. So, instead of using
<tt>Session.getStore(String)</tt>, you instead need to call
<tt>NewsStore.GetDefaultStore(Session)</tt>.
*/
public class NewsStore extends Store {
protected NNTPConnection nntp = null;
protected NewsRC newsrc = null;
protected NewsFolderRoot root_folder = null;
static protected NewsStore DefaultStore = null;
public static Store GetDefaultStore(Session s) {
if (DefaultStore == null) {
DefaultStore = new NewsStore(s);
}
return DefaultStore;
}
public NewsStore(Session s) {
super(s, null);
}
public NewsStore(Session s, URLName u) {
super(s, u);
}
NewsRC getNewsRC() {
return newsrc;
}
private void loadNewsRC(String host) throws IOException {
Assert.Assertion(newsrc == null);
String dir = System.getProperty("user.home");
boolean secure = false; // ####
String name = null;
if (Constants.ISUNIX) {
String name1 = (secure ? ".snewsrc" : ".newsrc");
String name2 = name1 + "-" + host;
if (new File(dir, name2).exists())
name = name2;
else if (new File(dir, name1).exists())
name = name1;
else
name = name2;
} else if (Constants.ISWINDOWS) {
String name1 = (secure ? "snews" : "news");
String name2 = name1 + "-" + host + ".rc";
String name3 = name1 + ".rc";
if (new File(dir, name2).exists())
name = name2;
else if (new File(dir, name3).exists())
name = name3;
else
name = name2;
} else {
Assert.NotYetImplemented("newsrc names only implemented for windows 'n' unix...");
}
File f = new File(dir, name);
newsrc = new NewsRC(f);
// If the newsrc file didn't exist, subscribe to some default newsgroups.
if (!f.exists()) {
String subs[] = getDefaultSubscriptions();
for (int i = 0; i < subs.length; i++) {
NewsRCLine ng = newsrc.getNewsgroup(subs[i]);
ng.setSubscribed(true);
}
}
}
protected boolean protocolConnect(String host,
int port,
String user,
String password)
throws MessagingException {
if (nntp != null)
return true; // Already connected.
if (host == null) {
// #### better name?
host = session.getProperty("mail.default_nntp_server");
if (host == null || host == "") {
// #### pop up a dialog box instead?
host = "news";
}
}
try {
loadNewsRC(host);
} catch (IOException e) {
throw new MessagingException("loading newsrc file", e);
}
nntp = new NNTPConnection();
try {
boolean status = nntp.connect(host, port, user, password);
if (!status) return false;
} catch (UnknownHostException e) { // This sucks, Beavis!
throw new MessagingException("Unknown host", e);
} catch (IOException e) {
throw new MessagingException("I/O Error", e);
}
if (!newsrc.file().exists()) {
// #### subscribe to the server's default groups
}
notifyStoreListeners(StoreEvent.NOTICE, "opened"); // #### ???
// notifyConnectionListeners(ConnectionEvent.OPENED);
return true;
}
public void close() {
if (nntp == null) {
// already closed.
Assert.Assertion(newsrc == null);
return;
}
nntp.close();
nntp = null;
Assert.Assertion(newsrc != null);
if (newsrc != null) {
try {
newsrc.save();
} catch (IOException e) {
// Sun doesn't allow us to signal here. Bastards...
// Just ignore it, I guess...
}
}
notifyStoreListeners(StoreEvent.NOTICE, "closed"); // #### ???
// notifyConnectionListeners(ConnectionEvent.CLOSED);
root_folder = null;
}
public Folder getDefaultFolder() {
if (root_folder == null) {
synchronized (this) {
if (root_folder == null) { // double check
root_folder = new NewsFolderRoot(this);
}
}
}
return root_folder;
}
public Folder getFolder(String name) throws MessagingException {
return getDefaultFolder().getFolder(name);
}
public Folder getFolder(URL url) {
Assert.NotYetImplemented("NewsStore.getFolder(URL)");
return null;
}
public Folder getFolder(URLName urlName) {
Assert.NotYetImplemented("NewsStore.getFolder(URLName)");
return null;
}
InputStream getMessageStream(NewsMessage message, boolean headers_too)
throws NNTPException, IOException {
Folder f = message.getFolder();
String group = (f == null ? null : f.getFullName());
int n = (group == null ? -1 : message.getStorageFolderIndex());
if (n == -1) {
/*
String id = #### ;
if (headers_too)
return nntp.ARTICLE(id);
else
return nntp.BODY(id);
*/
Assert.NotYetImplemented("NewsStore.getMessageStream via Message-ID");
return null;
} else {
if (headers_too)
return nntp.ARTICLE(group, n);
else
return nntp.BODY(group, n);
}
}
/** Returns array of int: [ nmessages low hi ]
*/
int[] getGroupCounts(NewsFolder folder) {
String group = folder.getFullName();
try {
return nntp.GROUP(group);
} catch (IOException e) {
return null;
}
}
/** Returns a list of newsgroups to which new users should be subscribed,
if they don't have a newsrc file. Tries to ask the news server for
this list; otherwise, uses some builtin defaults.
*/
String[] getDefaultSubscriptions() {
String s[] = null;
try {
s = nntp.LIST_SUBSCRIPTIONS();
} catch (NNTPException e) { // command unsupported
} catch (IOException e) { // something else
}
if (s == null || s.length == 0)
s = new String[] { "news.announce.newusers",
"news.newusers.questions",
"news.groups.questions",
"alt.fan.mozilla"
};
return s;
}
void openNewsgroup(NewsFolder folder, long from, long to) {
Enumeration e;
try {
e = nntp.getMessages(folder, from, to);
} catch (NNTPException ex) {
return;
} catch (IOException ex) {
return;
}
while (e.hasMoreElements()) {
Message m = (Message) e.nextElement();
folder.noticeInitialMessage(m);
}
}
}