pjs/grendel/filters/FilterMaster.java

227 строки
7.2 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.
*
* Class FilterMaster.
*
* Created: David Williams <djw@netscape.com>, 1 Oct 1997.
*/
package grendel.filters;
import java.io.Reader;
import java.io.FileReader;
import java.io.File;
import java.io.EOFException;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.util.Hashtable;
import java.util.Enumeration;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Store;
import javax.mail.Session;
import javax.mail.MessagingException;
import javax.mail.search.SearchTerm;
import javax.mail.search.SubjectTerm;
import javax.mail.search.FromTerm;
import javax.mail.event.MessageCountEvent;
import grendel.storage.BerkeleyStore;
import grendel.ui.StoreFactory;
import grendel.filters.FilterSyntaxException;
import grendel.filters.MoveFilterActionFactory;
import grendel.filters.DeleteFilterActionFactory;
import grendel.filters.SubjectTermFactory;
public class FilterMaster extends Object {
// class slots
static private FilterMaster fTheMaster = null;
// class methods
public static FilterMaster Get() {
if (fTheMaster == null)
fTheMaster = new FilterMaster();
return fTheMaster;
}
// instance slots
private Hashtable fFilters; // to hold named filters
private Hashtable fFilterActionFactories;
private Hashtable fFilterTermFactories;
// constructor API
private FilterMaster() {
fFilters = new Hashtable();
fFilterTermFactories = new Hashtable();
fFilterActionFactories = new Hashtable();
// Register built-in terms.
registerFilterTermFactory(new SubjectTermFactory());
// Register built-in filter actions.
registerFilterActionFactory(new MoveFilterActionFactory());
registerFilterActionFactory(new DeleteFilterActionFactory());
// Locate and read the filters description file.
String home_dir = System.getProperties().getProperty("user.home");
File home_dir_file = new File(home_dir);
File mail_filters_file = new File(home_dir_file, "mail.filters");
FileReader fr = null;
try {
fr = new FileReader(mail_filters_file);
} catch (FileNotFoundException e) {
System.err.println("mail.filters not found, skipping loadFilters()");
fr = null;
}
// We must do this as loadFilters calls Get(), and we don't want to
// go recursive. This is a reasonable thing to do, because at this
// point, the constructor has succeeded, so we know we will be the
// FilterMaster.
fTheMaster = this;
if (fr != null)
loadFilters(fr);
}
// instance methods
private void loadFilters(Reader reader) {
IFilter filter;
FilterRulesParser parser = new FilterRulesParser(reader);
try {
while ((filter = parser.getNext()) != null) {
String name = filter.toString();
// System.err.println("got filter: " + name);
fFilters.put(name, filter);
}
} catch (FilterSyntaxException e) {
System.err.println("Error in filter rules: " + e);
} catch (IOException e) {
System.err.println("IO error reading filter rules: " + e);
}
parser = null;
}
/*package*/
void registerFilterActionFactory(IFilterActionFactory factory) {
String key = factory.getName();
if (fFilterActionFactories.get(key) != null) {
// FIXME
System.err.println("FilterMaster.registerFilterAction(): duplicate");
return;
}
fFilterActionFactories.put(key, factory);
}
/*package*/
IFilterActionFactory getFilterActionFactory(String name) {
return (IFilterActionFactory)fFilterActionFactories.get(name);
}
/*package*/
void registerFilterTermFactory(IFilterTermFactory factory) {
String key = factory.getName();
if (fFilterTermFactories.get(key) != null) {
// FIXME
System.err.println("FilterMaster.registerFilterTerm(): duplicate");
return;
}
fFilterTermFactories.put(key, factory);
}
/*package*/
IFilterTermFactory getFilterTermFactory(String name) {
return (IFilterTermFactory)fFilterTermFactories.get(name);
}
// tell me what you can do. Something like this will need to be created
// so that you can build a UI. Caller uses object.toString() on the
// elements to create user visible labels, etc..
public Enumeration getFilterActionFactories() {
return fFilterActionFactories.elements();
}
public Enumeration getFilterTermFactories() {
return fFilterTermFactories.elements();
}
public Enumeration getFilters() {
return fFilters.elements();
}
// The verb that this whole sub-system is about. Apply all the defined
// filters to the specified message.
public void applyFilters(Message message) {
boolean deleted = false;
try {
deleted = message.isSet(Flags.Flag.DELETED);
} catch (MessagingException e) {
deleted = false;
}
if (deleted)
return; // don't need to be here
Enumeration filters = getFilters();
while (filters.hasMoreElements()) {
IFilter filter = (IFilter)filters.nextElement();
if (filter.match(message)) {
filter.exorcise(message);
break; // only do first match
}
}
}
// Utilities:
public Folder getFolder(String name) {
Session session = StoreFactory.Instance().getSession();
// ### Definitely wrong:
Store store = BerkeleyStore.GetDefaultStore(session);
Folder folder;
try {
folder = store.getFolder(name);
if (!folder.exists())
folder = null;
} catch (MessagingException e) {
folder = null;
}
return folder;
}
// For Testing.
public void applyFiltersToTestInbox() {
Folder inbox = getFolder("TestInbox");
if (inbox != null) {
synchronized (inbox) {
Message[] messages;
try {
messages = inbox.getMessages();
} catch (MessagingException e) {
messages = null;
}
if (messages != null) {
for (int i = 0; i < messages.length; i++) {
applyFilters(messages[i]);
}
}
}
}
}
}