forked from I2P_Developers/i2p.i2p
* SusiMail:
- Fix fetching of new mail - More Folder cleanup - Prep for not leaving on server - Prep for background checker
This commit is contained in:
@ -59,7 +59,7 @@ public class Folder<O extends Object> {
|
||||
}
|
||||
|
||||
private int pages, pageSize, currentPage;
|
||||
private O[] unsortedElements, elements;
|
||||
private O[] elements;
|
||||
private final Hashtable<String, Comparator<O>> sorter;
|
||||
private SortOrder sortingDirection;
|
||||
Comparator<O> currentSorter;
|
||||
@ -74,6 +74,7 @@ public class Folder<O extends Object> {
|
||||
|
||||
/**
|
||||
* Returns the current page.
|
||||
* Starts at 1, even if empty.
|
||||
*
|
||||
* @return Returns the current page.
|
||||
*/
|
||||
@ -83,6 +84,7 @@ public class Folder<O extends Object> {
|
||||
|
||||
/**
|
||||
* Sets the current page to the given parameter.
|
||||
* Starts at 1.
|
||||
*
|
||||
* @param currentPage The current page to set.
|
||||
*/
|
||||
@ -102,6 +104,7 @@ public class Folder<O extends Object> {
|
||||
|
||||
/**
|
||||
* Returns the number of pages in the folder.
|
||||
* Minimum of 1 even if empty.
|
||||
* @return Returns the number of pages.
|
||||
*/
|
||||
public synchronized int getPages() {
|
||||
@ -129,20 +132,6 @@ public class Folder<O extends Object> {
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of an array by copying its elements.
|
||||
*
|
||||
* @param source Array to copy.
|
||||
* @return Copy of source.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private O[] copyArray( O[] source )
|
||||
{
|
||||
Object[] destination = new Object[source.length];
|
||||
for( int i = 0; i < source.length; i++ )
|
||||
destination[i] = source[i];
|
||||
return (O[])destination;
|
||||
}
|
||||
/**
|
||||
* Recalculates variables.
|
||||
*/
|
||||
@ -166,30 +155,25 @@ public class Folder<O extends Object> {
|
||||
*/
|
||||
private void sort()
|
||||
{
|
||||
if( currentSorter != null ) {
|
||||
elements = copyArray( unsortedElements );
|
||||
if( currentSorter != null )
|
||||
Arrays.sort( elements, currentSorter );
|
||||
}
|
||||
else {
|
||||
elements = unsortedElements;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the array of objects the folder should manage.
|
||||
* Does NOT copy the array.
|
||||
*
|
||||
* @param elements Array of Os.
|
||||
*/
|
||||
public synchronized void setElements( O[] elements )
|
||||
{
|
||||
if (elements.length > 0) {
|
||||
this.unsortedElements = elements;
|
||||
this.elements = elements;
|
||||
if( currentSorter != null )
|
||||
sort();
|
||||
else
|
||||
this.elements = elements;
|
||||
} else
|
||||
} else {
|
||||
this.elements = null;
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
@ -198,7 +182,7 @@ public class Folder<O extends Object> {
|
||||
*
|
||||
* @param element to remove
|
||||
*/
|
||||
public synchronized void removeElement(O element) {
|
||||
public void removeElement(O element) {
|
||||
removeElements(Collections.singleton(element));
|
||||
}
|
||||
|
||||
@ -211,19 +195,49 @@ public class Folder<O extends Object> {
|
||||
public synchronized void removeElements(Collection<O> elems) {
|
||||
if (elements != null) {
|
||||
List<O> list = new ArrayList<O>(Arrays.asList(elements));
|
||||
boolean shouldUpdate = false;
|
||||
for (O e : elems) {
|
||||
list.remove(e);
|
||||
if (list.remove(e))
|
||||
shouldUpdate = true;
|
||||
}
|
||||
if (shouldUpdate) {
|
||||
elements = (O[]) list.toArray(new Object[list.size()]);
|
||||
update(); // will still be sorted
|
||||
}
|
||||
elements = (O[]) list.toArray(new Object[list.size()]);
|
||||
}
|
||||
if (unsortedElements != null) {
|
||||
List<O> list = new ArrayList<O>(Arrays.asList(unsortedElements));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an element only if it does not already exist
|
||||
*
|
||||
* @param element to add
|
||||
*/
|
||||
public void addElement(O element) {
|
||||
addElements(Collections.singleton(element));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add elements only if it they do not already exist
|
||||
*
|
||||
* @param elems to adde
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public synchronized void addElements(Collection<O> elems) {
|
||||
if (elements != null) {
|
||||
List<O> list = new ArrayList<O>(Arrays.asList(elements));
|
||||
boolean shouldUpdate = false;
|
||||
for (O e : elems) {
|
||||
list.remove(e);
|
||||
if (!list.contains(e)) {
|
||||
list.add(e);
|
||||
shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
if (shouldUpdate) {
|
||||
elements = (O[]) list.toArray(new Object[list.size()]);
|
||||
sort();
|
||||
update();
|
||||
}
|
||||
unsortedElements = (O[]) list.toArray(new Object[list.size()]);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,6 +24,7 @@
|
||||
package i2p.susi.webmail;
|
||||
|
||||
import i2p.susi.debug.Debug;
|
||||
import i2p.susi.util.Config;
|
||||
import i2p.susi.util.ReadBuffer;
|
||||
import i2p.susi.webmail.pop3.POP3MailBox;
|
||||
import i2p.susi.webmail.pop3.POP3MailBox.FetchRequest;
|
||||
@ -136,8 +137,10 @@ class MailCache {
|
||||
}
|
||||
}
|
||||
if (disk != null) {
|
||||
if (disk.saveMail(mail) && mail.hasBody()) {
|
||||
// TODO delete on server
|
||||
if (disk.saveMail(mail) && mail.hasBody() &&
|
||||
false && // TO ENABLE
|
||||
!Boolean.parseBoolean(Config.getProperty(WebMail.CONFIG_LEAVE_ON_SERVER))) {
|
||||
mailbox.queueForDeletion(mail.uidl);
|
||||
}
|
||||
}
|
||||
return mail;
|
||||
@ -146,18 +149,23 @@ class MailCache {
|
||||
/**
|
||||
* Fetch any needed data from pop3 server.
|
||||
* Mail objects are inserted into the requests.
|
||||
* After this, call getUIDLs() to get all known mail UIDLs.
|
||||
* MUST already be connected, otherwise returns false.
|
||||
*
|
||||
* @return true if any were fetched
|
||||
* @since 0.9.13
|
||||
*/
|
||||
public void getMail(Collection<MailRequest> requests) {
|
||||
public boolean getMail(boolean hOnly) {
|
||||
|
||||
Collection<String> popKnown = mailbox.getUIDLs();
|
||||
if (popKnown == null)
|
||||
return false;
|
||||
List<POP3Request> fetches = new ArrayList<POP3Request>();
|
||||
// Fill in the answers from the cache and make a list of
|
||||
// requests.to send off
|
||||
for (MailRequest mr : requests) {
|
||||
for (String uidl : popKnown) {
|
||||
Mail mail = null, newMail = null;
|
||||
String uidl = mr.getUIDL();
|
||||
boolean headerOnly = mr.getHeaderOnly();
|
||||
boolean headerOnly = hOnly;
|
||||
|
||||
/*
|
||||
* synchronize update to hashtable
|
||||
@ -175,7 +183,6 @@ class MailCache {
|
||||
}
|
||||
if (mail.markForDeletion)
|
||||
continue;
|
||||
mr.setMail(mail);
|
||||
int sz = mail.getSize();
|
||||
if (sz > 0 && sz <= FETCH_ALL_SIZE)
|
||||
headerOnly = false;
|
||||
@ -187,7 +194,7 @@ class MailCache {
|
||||
continue; // found on disk, woo
|
||||
}
|
||||
}
|
||||
POP3Request pr = new POP3Request(mr, mail, true);
|
||||
POP3Request pr = new POP3Request(mail, true);
|
||||
fetches.add(pr);
|
||||
}
|
||||
} else {
|
||||
@ -198,12 +205,13 @@ class MailCache {
|
||||
continue; // found on disk, woo
|
||||
}
|
||||
}
|
||||
POP3Request pr = new POP3Request(mr, mail, false);
|
||||
POP3Request pr = new POP3Request(mail, false);
|
||||
fetches.add(pr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean rv = false;
|
||||
if (!fetches.isEmpty()) {
|
||||
// Send off the fetches
|
||||
// gaah compiler
|
||||
@ -220,14 +228,18 @@ class MailCache {
|
||||
} else {
|
||||
mail.setBody(rb);
|
||||
}
|
||||
rv = true;
|
||||
if (disk != null) {
|
||||
if (disk.saveMail(mail) && mail.hasBody()) {
|
||||
// TODO delete on server
|
||||
if (disk.saveMail(mail) && mail.hasBody() &&
|
||||
false && // TO ENABLE
|
||||
!Boolean.parseBoolean(Config.getProperty(WebMail.CONFIG_LEAVE_ON_SERVER))) {
|
||||
mailbox.queueForDeletion(mail.uidl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -264,32 +276,21 @@ class MailCache {
|
||||
mailbox.queueForDeletion(toDelete);
|
||||
}
|
||||
|
||||
/**
|
||||
* Incoming to us
|
||||
*/
|
||||
public interface MailRequest {
|
||||
public String getUIDL();
|
||||
public boolean getHeaderOnly();
|
||||
public void setMail(Mail mail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Outgoing to POP3
|
||||
*/
|
||||
private static class POP3Request implements FetchRequest {
|
||||
public final MailRequest request;
|
||||
public final Mail mail;
|
||||
private final boolean headerOnly;
|
||||
public ReadBuffer buf;
|
||||
|
||||
public POP3Request(MailRequest req, Mail m, boolean hOnly) {
|
||||
request = req;
|
||||
public POP3Request(Mail m, boolean hOnly) {
|
||||
mail = m;
|
||||
headerOnly = hOnly;
|
||||
}
|
||||
|
||||
public String getUIDL() {
|
||||
return request.getUIDL();
|
||||
return mail.uidl;
|
||||
}
|
||||
|
||||
public boolean getHeaderOnly() {
|
||||
|
@ -174,7 +174,7 @@ public class WebMail extends HttpServlet
|
||||
private static final String CONFIG_COMPOSER_ROWS = "composer.rows";
|
||||
|
||||
private static final String CONFIG_BCC_TO_SELF = "composer.bcc.to.self";
|
||||
private static final String CONFIG_LEAVE_ON_SERVER = "pop3.leave.on.server";
|
||||
static final String CONFIG_LEAVE_ON_SERVER = "pop3.leave.on.server";
|
||||
private static final String CONFIG_DEBUG = "debug";
|
||||
|
||||
private static final String RC_PROP_THEME = "routerconsole.theme";
|
||||
@ -676,18 +676,14 @@ public class WebMail extends HttpServlet
|
||||
MailCache mc = new MailCache(mailbox, host, pop3PortNo, user, pass);
|
||||
sessionObject.mailCache = mc;
|
||||
sessionObject.folder = new Folder<String>();
|
||||
if (!offline) {
|
||||
// prime the cache, request all headers at once
|
||||
// otherwise they are pulled one at a time by sortBy() below
|
||||
mc.getMail(true);
|
||||
}
|
||||
// get through cache so we have the disk-only ones too
|
||||
String[] uidls = mc.getUIDLs();
|
||||
sessionObject.folder.setElements(uidls);
|
||||
if (uidls.length > 0 && !offline) {
|
||||
// prime the cache, request all headers at once
|
||||
// otherwise they are pulled one at a time by sortBy() below
|
||||
List<MailCache.MailRequest> reqs = new ArrayList<MailCache.MailRequest>(uidls.length);
|
||||
for (int i = 0; i < uidls.length; i++) {
|
||||
reqs.add(new CacheRequest(uidls[i]));
|
||||
}
|
||||
mc.getMail(reqs);
|
||||
}
|
||||
|
||||
//sessionObject.folder.addSorter( SORT_ID, new IDSorter( sessionObject.mailCache ) );
|
||||
sessionObject.folder.addSorter( SORT_SENDER, new SenderSorter( sessionObject.mailCache ) );
|
||||
@ -714,30 +710,6 @@ public class WebMail extends HttpServlet
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Outgoing to MailCache
|
||||
* @since 0.9.13
|
||||
*/
|
||||
private static class CacheRequest implements MailCache.MailRequest {
|
||||
private final String uidl;
|
||||
|
||||
public CacheRequest(String uidl) {
|
||||
this.uidl = uidl;
|
||||
}
|
||||
|
||||
public String getUIDL() {
|
||||
return uidl;
|
||||
}
|
||||
|
||||
public boolean getHeaderOnly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setMail(Mail mail) {
|
||||
// do nothing, this just pumps up the cache
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param sessionObject
|
||||
@ -1036,6 +1008,7 @@ public class WebMail extends HttpServlet
|
||||
}
|
||||
if( buttonPressed( request, REFRESH ) ) {
|
||||
sessionObject.mailbox.refresh();
|
||||
sessionObject.mailCache.getMail(true);
|
||||
// get through cache so we have the disk-only ones too
|
||||
String[] uidls = sessionObject.mailCache.getUIDLs();
|
||||
if (uidls != null)
|
||||
@ -1461,8 +1434,10 @@ public class WebMail extends HttpServlet
|
||||
if( sessionObject.state != STATE_AUTH ) {
|
||||
// get through cache so we have the disk-only ones too
|
||||
String[] uidls = sessionObject.mailCache.getUIDLs();
|
||||
if (uidls != null)
|
||||
if (uidls != null) {
|
||||
// TODO why every time?
|
||||
sessionObject.folder.setElements(uidls);
|
||||
}
|
||||
}
|
||||
|
||||
if( ! sendAttachment( sessionObject, response ) ) {
|
||||
@ -1852,7 +1827,7 @@ public class WebMail extends HttpServlet
|
||||
out.println(
|
||||
"<tr><td colspan=\"2\"> </td></tr>\n" +
|
||||
"<tr><td></td><td align=\"left\">" + button( LOGIN, _("Login") ) + spacer +
|
||||
button(OFFLINE, _("View Mail Offline") ) + spacer +
|
||||
button(OFFLINE, _("Read Mail Offline") ) + spacer +
|
||||
" <input class=\"cancel\" type=\"reset\" value=\"" + _("Reset") + "\"></td></tr>\n" +
|
||||
"<tr><td colspan=\"2\"> </td></tr>\n" +
|
||||
"<tr><td></td><td align=\"left\"><a href=\"http://hq.postman.i2p/?page_id=14\">" + _("Learn about I2P mail") + "</a></td></tr>\n" +
|
||||
|
@ -71,8 +71,10 @@ class DelayedDeleter {
|
||||
isDeleting = true;
|
||||
t.start();
|
||||
} else {
|
||||
Debug.debug(Debug.DEBUG, "Nothing to delete");
|
||||
Debug.debug(Debug.DEBUG, "Not deleting, only idle " + idle);
|
||||
}
|
||||
} else {
|
||||
Debug.debug(Debug.DEBUG, "Nothing to delete");
|
||||
}
|
||||
schedule(CHECK_TIME);
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ public class POP3MailBox {
|
||||
|
||||
private Socket socket;
|
||||
private final AtomicLong lastActive;
|
||||
private final AtomicLong lastChecked;
|
||||
|
||||
private final Object synchronizer;
|
||||
private final DelayedDeleter delayedDeleter;
|
||||
@ -92,6 +93,7 @@ public class POP3MailBox {
|
||||
// this appears in the UI so translate
|
||||
lastLine = _("No response from server");
|
||||
lastActive = new AtomicLong(System.currentTimeMillis());
|
||||
lastChecked = new AtomicLong();
|
||||
delayedDeleter = new DelayedDeleter(this);
|
||||
}
|
||||
|
||||
@ -270,10 +272,20 @@ public class POP3MailBox {
|
||||
*/
|
||||
public void queueForDeletion(Collection<String> uidls) {
|
||||
for (String uidl : uidls) {
|
||||
delayedDeleter.queueDelete(uidl);
|
||||
queueForDeletion(uidl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue for later deletion. Non-blocking.
|
||||
*
|
||||
* @since 0.9.13
|
||||
*/
|
||||
public void queueForDeletion(String uidl) {
|
||||
Debug.debug(Debug.DEBUG, "Queueing for deletion: " + uidl);
|
||||
delayedDeleter.queueDelete(uidl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all at once and close. Does not reconnect.
|
||||
* Do NOT call performDelete() after this.
|
||||
@ -445,6 +457,15 @@ public class POP3MailBox {
|
||||
return lastActive.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp. When we last successfully got the UIDL list.
|
||||
*
|
||||
* @since 0.9.13
|
||||
*/
|
||||
long getLastChecked() {
|
||||
return lastChecked.get();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param response line starting with +OK
|
||||
@ -489,6 +510,7 @@ public class POP3MailBox {
|
||||
}
|
||||
}
|
||||
}
|
||||
lastChecked.set(System.currentTimeMillis());
|
||||
} else {
|
||||
Debug.debug(Debug.DEBUG, "Error getting UIDL list from server.");
|
||||
}
|
||||
@ -1085,12 +1107,12 @@ public class POP3MailBox {
|
||||
*
|
||||
* @return A new array of the available UIDLs. No particular order.
|
||||
*/
|
||||
public String[] getUIDLs()
|
||||
public Collection<String> getUIDLs()
|
||||
{
|
||||
if (!isConnected())
|
||||
return null;
|
||||
synchronized( synchronizer ) {
|
||||
return uidlToID.keySet().toArray(new String[uidlToID.size()]);
|
||||
return new ArrayList(uidlToID.keySet());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
* SusiMail:
|
||||
- Queue deletions for a later thread
|
||||
- Synch all folder access
|
||||
- Fix fetching of new mail
|
||||
|
||||
2014-04-22 zzz
|
||||
* SusiMail:
|
||||
|
@ -18,7 +18,7 @@ public class RouterVersion {
|
||||
/** deprecated */
|
||||
public final static String ID = "Monotone";
|
||||
public final static String VERSION = CoreVersion.VERSION;
|
||||
public final static long BUILD = 9;
|
||||
public final static long BUILD = 10;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
Reference in New Issue
Block a user