зеркало из https://github.com/mozilla/pjs.git
227 строки
7.2 KiB
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]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|