1998-09-09 00:52:38 +00:00
|
|
|
/* -*- 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: Will Scullin <scullin@netscape.com>, 2 Dec 1997.
|
1999-03-07 02:39:04 +00:00
|
|
|
*
|
|
|
|
* Contributors: Jeff Galyan <talisman@anamorphic.com>
|
|
|
|
* Giao Nguyen <grail@cafebabe.org>
|
1999-06-15 11:44:40 +00:00
|
|
|
* Edwin Woudt <edwin@woudt.nl>
|
1998-09-09 00:52:38 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
package grendel.view;
|
|
|
|
|
|
|
|
import java.util.Vector;
|
|
|
|
|
|
|
|
import javax.mail.AuthenticationFailedException;
|
|
|
|
import javax.mail.Folder;
|
|
|
|
import javax.mail.MessagingException;
|
|
|
|
import javax.mail.Store;
|
1999-03-01 05:20:27 +00:00
|
|
|
import javax.mail.URLName;
|
1998-09-09 00:52:38 +00:00
|
|
|
import javax.mail.event.ConnectionEvent;
|
|
|
|
import javax.mail.event.ConnectionListener;
|
|
|
|
import javax.mail.event.FolderEvent;
|
|
|
|
import javax.mail.event.FolderListener;
|
|
|
|
|
1999-01-09 03:55:32 +00:00
|
|
|
import javax.swing.JOptionPane;
|
|
|
|
import javax.swing.event.EventListenerList;
|
1998-09-09 00:52:38 +00:00
|
|
|
|
1999-06-15 11:44:40 +00:00
|
|
|
import grendel.prefs.base.ServerArray;
|
|
|
|
import grendel.prefs.base.IdentityStructure;
|
1998-09-09 00:52:38 +00:00
|
|
|
import grendel.storage.FolderExtraFactory;
|
|
|
|
|
|
|
|
public class ViewedStoreBase extends ViewedFolderBase implements ViewedStore {
|
|
|
|
|
1999-06-15 11:44:40 +00:00
|
|
|
int fID;
|
|
|
|
|
1998-09-09 00:52:38 +00:00
|
|
|
Vector fUpdateQueue;
|
|
|
|
Thread fUpdateThread;
|
|
|
|
|
|
|
|
ViewedFolder fDefaultFolder;
|
|
|
|
Store fStore;
|
1999-06-15 11:44:40 +00:00
|
|
|
|
1998-09-09 00:52:38 +00:00
|
|
|
ViewedStore fNext;
|
|
|
|
boolean fConnected;
|
|
|
|
|
|
|
|
int fVisible = kSubscribed;
|
|
|
|
|
|
|
|
EventListenerList fListeners = new EventListenerList();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ViewedStoreBase constructor. This should be called before any
|
|
|
|
* attempt to connect so that it can reflect the correct connection
|
|
|
|
* state.
|
|
|
|
*/
|
|
|
|
|
1999-06-15 11:44:40 +00:00
|
|
|
public ViewedStoreBase(Store aStore, int aID) {
|
1998-09-09 00:52:38 +00:00
|
|
|
super(null, null, null);
|
1999-06-15 11:44:40 +00:00
|
|
|
|
|
|
|
fID = aID;
|
1998-09-09 00:52:38 +00:00
|
|
|
fViewedStore = this;
|
|
|
|
fStore = aStore;
|
|
|
|
|
|
|
|
fStore.addConnectionListener(new StoreConnectionListener());
|
|
|
|
}
|
|
|
|
|
1999-06-15 11:44:40 +00:00
|
|
|
/**
|
|
|
|
* Returns the id which identifies this store in the preferences/
|
|
|
|
*/
|
|
|
|
|
|
|
|
public int getID() {
|
|
|
|
return fID;
|
|
|
|
}
|
|
|
|
|
1998-09-09 00:52:38 +00:00
|
|
|
/**
|
|
|
|
* Returns the associated folder
|
|
|
|
*/
|
|
|
|
|
|
|
|
public Folder getFolder() {
|
|
|
|
try {
|
|
|
|
getDefaultFolder();
|
|
|
|
return super.getFolder();
|
|
|
|
} catch (MessagingException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the associated store.
|
|
|
|
*/
|
|
|
|
|
|
|
|
public Store getStore() {
|
|
|
|
return fStore;
|
|
|
|
}
|
|
|
|
|
1999-03-01 05:20:27 +00:00
|
|
|
public boolean isLocal() {
|
|
|
|
URLName url = fStore.getURLName();
|
|
|
|
return (url.getProtocol().equals("berkeley"));
|
|
|
|
}
|
|
|
|
|
1998-09-09 00:52:38 +00:00
|
|
|
/**
|
|
|
|
* Returns the store's default folder wrapped in a ViewedFolder
|
|
|
|
* object.
|
|
|
|
*/
|
|
|
|
|
|
|
|
public ViewedFolder getDefaultFolder() throws MessagingException {
|
|
|
|
if (fDefaultFolder == null) {
|
|
|
|
checkConnected();
|
1999-03-01 05:28:18 +00:00
|
|
|
if (isConnected()) {
|
1998-09-09 00:52:38 +00:00
|
|
|
fDefaultFolder = new ViewedFolderBase(this, null,
|
|
|
|
fStore.getDefaultFolder());
|
|
|
|
|
|
|
|
setFolder(fDefaultFolder.getFolder());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return fDefaultFolder;
|
|
|
|
}
|
|
|
|
|
1999-06-15 11:44:40 +00:00
|
|
|
/**
|
|
|
|
* Returns the description for this store
|
|
|
|
*/
|
|
|
|
|
|
|
|
public String getDescription() {
|
|
|
|
return ServerArray.GetMaster().get(fID).getDescription();
|
|
|
|
}
|
|
|
|
|
1999-06-20 21:41:16 +00:00
|
|
|
/**
|
|
|
|
* Returns the name for this store. This is the same as the description.
|
|
|
|
*/
|
|
|
|
|
|
|
|
public String getName() {
|
|
|
|
return getDescription();
|
|
|
|
}
|
|
|
|
|
1998-09-09 00:52:38 +00:00
|
|
|
/**
|
|
|
|
* Returns the protocol used by this store.
|
|
|
|
*/
|
|
|
|
|
|
|
|
public String getProtocol() {
|
1999-06-15 11:44:40 +00:00
|
|
|
return ServerArray.GetMaster().get(fID).getType();
|
1998-09-09 00:52:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the host for this store. Returns null for a local store.
|
|
|
|
*/
|
|
|
|
|
|
|
|
public String getHost() {
|
1999-06-15 11:44:40 +00:00
|
|
|
return ServerArray.GetMaster().get(fID).getHost();
|
1998-09-09 00:52:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the user name used to connect. May return null if
|
|
|
|
* no user name was used.
|
|
|
|
*/
|
|
|
|
|
|
|
|
public String getUsername() {
|
1999-06-15 11:44:40 +00:00
|
|
|
return ServerArray.GetMaster().get(fID).getUsername();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the password.
|
|
|
|
*/
|
|
|
|
|
|
|
|
public String getPassword() {
|
|
|
|
return ServerArray.GetMaster().get(fID).getPassword();
|
1998-09-09 00:52:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the port used to connect. Returns -1 for the protocol default.
|
|
|
|
*/
|
|
|
|
|
|
|
|
public int getPort() {
|
1999-06-15 11:44:40 +00:00
|
|
|
return ServerArray.GetMaster().get(fID).getPort();
|
1998-09-09 00:52:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the connected state of this store
|
|
|
|
*/
|
|
|
|
|
|
|
|
public boolean isConnected() {
|
1999-03-01 05:28:18 +00:00
|
|
|
return ((isLocal()) ? true : fConnected);
|
1998-09-09 00:52:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a ViewedStoreListener
|
|
|
|
*/
|
|
|
|
|
|
|
|
public void addViewedStoreListener(ViewedStoreListener l) {
|
|
|
|
fListeners.add(ViewedStoreListener.class, l);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes a ViewedStoreListener
|
|
|
|
*/
|
|
|
|
|
|
|
|
public void removeViewedStoreListener(ViewedStoreListener l) {
|
|
|
|
fListeners.remove(ViewedStoreListener.class, l);
|
|
|
|
}
|
|
|
|
|
1999-03-01 05:20:27 +00:00
|
|
|
void connectStore() {
|
|
|
|
try {
|
|
|
|
if (fStore != null) {
|
1999-06-15 11:44:40 +00:00
|
|
|
fStore.connect(getHost(), getPort(), getUsername(), getPassword());
|
1999-03-01 05:20:27 +00:00
|
|
|
}
|
|
|
|
} catch (AuthenticationFailedException e) {
|
|
|
|
JOptionPane.showMessageDialog(null,
|
|
|
|
// labels.getString("loginFailedLabel"),
|
|
|
|
// labels.getString("errorDialogLabel"),
|
|
|
|
"Login failed",
|
|
|
|
"Grendel Error",
|
|
|
|
JOptionPane.ERROR_MESSAGE);
|
|
|
|
|
|
|
|
} catch (MessagingException e) {
|
|
|
|
System.out.println("Got exception " + e +
|
|
|
|
" while connecting to " + this);
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-09-09 00:52:38 +00:00
|
|
|
void checkConnected() throws MessagingException {
|
|
|
|
if (!isConnected()) {
|
1999-06-15 11:44:40 +00:00
|
|
|
//Thread connect = new Thread(new ConnectThread());
|
|
|
|
//connect.start();
|
|
|
|
connectStore();
|
1998-09-09 00:52:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
boolean isSorted() {
|
1999-06-15 11:44:40 +00:00
|
|
|
return true;
|
1998-09-09 00:52:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets which children to show for this store
|
|
|
|
*/
|
|
|
|
|
|
|
|
public void setVisible(int aVisible) {
|
|
|
|
fVisible = aVisible;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns which children are showing for this store
|
|
|
|
*/
|
|
|
|
|
|
|
|
public int getVisible() {
|
|
|
|
return fVisible;
|
|
|
|
}
|
|
|
|
|
|
|
|
public String toString() {
|
1999-06-15 11:44:40 +00:00
|
|
|
return ServerArray.GetMaster().get(fID).getDescription();
|
1998-09-09 00:52:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void addFolderUpdate(ViewedFolderBase aFolder) {
|
|
|
|
if (fUpdateQueue == null) {
|
|
|
|
fUpdateQueue = new Vector();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fUpdateQueue.contains(aFolder)) {
|
|
|
|
fUpdateQueue.addElement(aFolder);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fUpdateThread == null) {
|
|
|
|
fUpdateThread = new Thread(new UpdateCountThread(), "MsgCount");
|
|
|
|
fUpdateThread.setPriority(Thread.MIN_PRIORITY);
|
|
|
|
fUpdateThread.start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void notifyFolderChanged(ViewedFolderBase aFolder) {
|
|
|
|
Object[] listeners = fListeners.getListenerList();
|
|
|
|
ViewedStoreEvent event = null;
|
|
|
|
for (int i = 0; i < listeners.length - 1; i += 2) {
|
|
|
|
// Lazily create the event:
|
|
|
|
if (event == null)
|
|
|
|
event = new ViewedStoreEvent(this, aFolder);
|
|
|
|
((ViewedStoreListener)listeners[i+1]).folderChanged(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-01-10 22:09:06 +00:00
|
|
|
void notifyFolderDeleted(ViewedFolderBase aFolder) {
|
|
|
|
// throws MessagingException {
|
|
|
|
try {
|
1998-09-09 00:52:38 +00:00
|
|
|
if (!aFolder.getFolder().exists()) {
|
|
|
|
Object[] listeners = fListeners.getListenerList();
|
|
|
|
ViewedStoreEvent event = null;
|
|
|
|
for (int i = 0; i < listeners.length - 1; i += 2) {
|
|
|
|
// Lazily create the event:
|
|
|
|
if (event == null)
|
|
|
|
event = new ViewedStoreEvent(this, aFolder);
|
|
|
|
((ViewedStoreListener)listeners[i+1]).folderChanged(event);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
notifyFolderChanged(aFolder);
|
|
|
|
}
|
1999-01-10 22:09:06 +00:00
|
|
|
} catch (MessagingException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
1998-09-09 00:52:38 +00:00
|
|
|
}
|
|
|
|
|
1999-01-09 03:55:32 +00:00
|
|
|
void notifyFolderCreated(Folder aFolder) {
|
1999-01-10 22:09:06 +00:00
|
|
|
try{
|
1998-09-09 00:52:38 +00:00
|
|
|
if (aFolder.getParent() != null) {
|
|
|
|
try {
|
|
|
|
ViewedFolderBase parent =
|
|
|
|
(ViewedFolderBase) getViewedFolder(aFolder.getParent());
|
|
|
|
parent.addSubFolder(new ViewedFolderBase(this, parent, aFolder));
|
|
|
|
} catch (MessagingException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
throw new IllegalStateException("Can't create default folder?");
|
|
|
|
}
|
1999-01-10 22:09:06 +00:00
|
|
|
} catch (MessagingException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
1998-09-09 00:52:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class StoreConnectionListener implements ConnectionListener {
|
|
|
|
public void closed(ConnectionEvent aEvent) {
|
|
|
|
fConnected = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void disconnected(ConnectionEvent aEvent) {
|
|
|
|
// XXX Maybe throw up dialog?
|
|
|
|
fConnected = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void opened(ConnectionEvent aEvent) {
|
|
|
|
fConnected = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class StoreFolderListener implements FolderListener {
|
|
|
|
public void folderCreated(FolderEvent e) {
|
|
|
|
notifyFolderCreated(e.getFolder());
|
|
|
|
}
|
|
|
|
|
|
|
|
public void folderDeleted(FolderEvent e) {
|
|
|
|
// We'll let ViewedFolderBase handle this
|
|
|
|
}
|
|
|
|
|
|
|
|
public void folderRenamed(FolderEvent e) {
|
|
|
|
// We'll let ViewedFolderBase handle this
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-03-01 01:04:19 +00:00
|
|
|
class ConnectThread implements Runnable {
|
|
|
|
public void run() {
|
1999-03-01 05:20:27 +00:00
|
|
|
connectStore();
|
1999-03-01 01:04:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-09-09 00:52:38 +00:00
|
|
|
class UpdateCountThread implements Runnable {
|
|
|
|
void updateFolder(ViewedFolderBase viewedFolder) {
|
|
|
|
try {
|
|
|
|
Folder folder = viewedFolder.getFolder();
|
|
|
|
if (folder != null) {
|
|
|
|
if (!folder.isOpen()) {
|
1999-06-14 21:52:28 +00:00
|
|
|
try {
|
|
|
|
folder.open(Folder.READ_WRITE);
|
|
|
|
} catch (MessagingException e) {
|
|
|
|
folder.open(Folder.READ_ONLY);
|
|
|
|
}
|
1998-09-09 00:52:38 +00:00
|
|
|
}
|
|
|
|
int messageCount = folder.getMessageCount();
|
|
|
|
int unreadCount = folder.getUnreadMessageCount();
|
|
|
|
int undeletedCount =
|
|
|
|
FolderExtraFactory.Get(folder).getUndeletedMessageCount();
|
|
|
|
viewedFolder.setCounts(messageCount, unreadCount, undeletedCount);
|
|
|
|
}
|
|
|
|
} catch (MessagingException e) {
|
1999-06-15 11:44:40 +00:00
|
|
|
e.printStackTrace();
|
1998-09-09 00:52:38 +00:00
|
|
|
} catch (IllegalStateException e) {
|
1999-06-15 11:44:40 +00:00
|
|
|
e.printStackTrace();
|
1998-09-09 00:52:38 +00:00
|
|
|
} catch (Exception e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void run() {
|
|
|
|
while (!Thread.interrupted()) {
|
|
|
|
if (fUpdateQueue.size() > 0) {
|
|
|
|
ViewedFolderBase folder =
|
|
|
|
(ViewedFolderBase) fUpdateQueue.firstElement();
|
|
|
|
updateFolder(folder);
|
|
|
|
fUpdateQueue.removeElement(folder);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
Thread.sleep(100);
|
|
|
|
} catch (InterruptedException e) {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|