X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Fcx%2Ffbn%2Fnevernote%2Fthreads%2FSyncRunner.java;h=ecd18c4a4d0cc5ac4e6468e2feb39bb0cfb67106;hb=7b79a07951a083236298195d0214c9748ce38569;hp=68dbd02e089ef159533e2b55806563ac1e4624c8;hpb=a50536d87873bce8f9ead5987dcf03f25834b949;p=neighbornote%2FNeighborNote.git diff --git a/src/cx/fbn/nevernote/threads/SyncRunner.java b/src/cx/fbn/nevernote/threads/SyncRunner.java index 68dbd02..ecd18c4 100644 --- a/src/cx/fbn/nevernote/threads/SyncRunner.java +++ b/src/cx/fbn/nevernote/threads/SyncRunner.java @@ -1,2080 +1,2224 @@ -/* - * This file is part of NixNote - * Copyright 2009 Randy Baumgarte - * - * This file may be licensed under the terms of of the - * GNU General Public License Version 2 (the ``GPL''). - * - * Software distributed under the License is distributed - * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the GPL for the specific language - * governing rights and limitations. - * - * You should have received a copy of the GPL along with this - * program. If not, go to http://www.gnu.org/licenses/gpl.html - * or write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * -*/ -package cx.fbn.nevernote.threads; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.List; -import java.util.TreeSet; -import java.util.Vector; -import java.util.concurrent.LinkedBlockingQueue; - -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpClient; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.protocol.HTTP; -import org.apache.thrift.TException; -import org.apache.thrift.protocol.TBinaryProtocol; -import org.apache.thrift.transport.THttpClient; -import org.apache.thrift.transport.TTransportException; - -import com.evernote.edam.error.EDAMNotFoundException; -import com.evernote.edam.error.EDAMSystemException; -import com.evernote.edam.error.EDAMUserException; -import com.evernote.edam.notestore.NoteStore; -import com.evernote.edam.notestore.NoteStore.Client; -import com.evernote.edam.notestore.SyncChunk; -import com.evernote.edam.notestore.SyncState; -import com.evernote.edam.type.Data; -import com.evernote.edam.type.LinkedNotebook; -import com.evernote.edam.type.Note; -import com.evernote.edam.type.Notebook; -import com.evernote.edam.type.Resource; -import com.evernote.edam.type.SavedSearch; -import com.evernote.edam.type.SharedNotebook; -import com.evernote.edam.type.Tag; -import com.evernote.edam.type.User; -import com.evernote.edam.userstore.AuthenticationResult; -import com.evernote.edam.userstore.UserStore; -import com.trolltech.qt.core.QByteArray; -import com.trolltech.qt.core.QFile; -import com.trolltech.qt.core.QIODevice.OpenModeFlag; -import com.trolltech.qt.core.QObject; -import com.trolltech.qt.core.QTextCodec; -import com.trolltech.qt.gui.QMessageBox; - -import cx.fbn.nevernote.signals.NoteIndexSignal; -import cx.fbn.nevernote.signals.NoteResourceSignal; -import cx.fbn.nevernote.signals.NoteSignal; -import cx.fbn.nevernote.signals.NotebookSignal; -import cx.fbn.nevernote.signals.SavedSearchSignal; -import cx.fbn.nevernote.signals.StatusSignal; -import cx.fbn.nevernote.signals.SyncSignal; -import cx.fbn.nevernote.signals.TagSignal; -import cx.fbn.nevernote.sql.DatabaseConnection; -import cx.fbn.nevernote.sql.DeletedItemRecord; -import cx.fbn.nevernote.utilities.ApplicationLogger; - -public class SyncRunner extends QObject implements Runnable { - - private final ApplicationLogger logger; - private DatabaseConnection conn; - private boolean idle; - public boolean error; - public volatile Vector errorSharedNotebooks; - public volatile HashMap errorSharedNotebooksIgnored; - public volatile boolean isConnected; - public volatile boolean keepRunning; - public volatile String authToken; - private long evernoteUpdateCount; - private final String userAgent = "NixNote/" + System.getProperty("os.name") - +"/"+System.getProperty("java.vendor") + "/" - + System.getProperty("java.version") +";"; - - public volatile NoteStore.Client localNoteStore; - private UserStore.Client userStore; - - public volatile StatusSignal status; - public volatile TagSignal tagSignal; - public volatile NotebookSignal notebookSignal; - public volatile NoteIndexSignal noteIndexSignal; - public volatile NoteSignal noteSignal; - public volatile SavedSearchSignal searchSignal; - public volatile NoteResourceSignal resourceSignal; - public volatile SyncSignal syncSignal; - public volatile boolean authRefreshNeeded; - public volatile boolean syncNeeded; - public volatile boolean disableUploads; - public volatile boolean syncDeletedContent; - private volatile Vector dirtyNoteGuids; - - public volatile String username = ""; - public volatile String password = ""; - public volatile String userStoreUrl; - private final static String consumerKey = "baumgarte"; - private final static String consumerSecret = "eb8b5740e17cb55f"; - public String noteStoreUrlBase; - private THttpClient userStoreTrans; - private TBinaryProtocol userStoreProt; - private AuthenticationResult authResult; - private AuthenticationResult linkedAuthResult; - private User user; - private long authTimeRemaining; - public long authRefreshTime; - public long failedRefreshes = 0; - public THttpClient noteStoreTrans; - public TBinaryProtocol noteStoreProt; - public String noteStoreUrl; - public long sequenceDate; - public int updateSequenceNumber; - private boolean refreshNeeded; - private volatile LinkedBlockingQueue workQueue; - private static int MAX_QUEUED_WAITING = 1000; - String dbuid; - String dburl; - String indexUrl; - String resourceUrl; - String dbpswd; - String dbcpswd; - private final TreeSet ignoreTags; - private final TreeSet ignoreNotebooks; - private final TreeSet ignoreLinkedNotebooks; - private HashMap badTagSync; - - - - public SyncRunner(String logname, String u, String i, String r, String uid, String pswd, String cpswd) { - logger = new ApplicationLogger(logname); - - noteSignal = new NoteSignal(); - status = new StatusSignal(); - tagSignal = new TagSignal(); - notebookSignal = new NotebookSignal(); - noteIndexSignal = new NoteIndexSignal(); - noteSignal = new NoteSignal(); - searchSignal = new SavedSearchSignal(); - syncSignal = new SyncSignal(); - resourceSignal = new NoteResourceSignal(); - resourceUrl = r; - indexUrl = i; - dbuid = uid; - dburl = u; - dbpswd = pswd; - dbcpswd = cpswd; -// this.setAutoDelete(false); - - isConnected = false; - syncNeeded = false; - authRefreshNeeded = false; - keepRunning = true; - idle = true; - disableUploads = false; - ignoreTags = new TreeSet(); - ignoreNotebooks = new TreeSet(); - ignoreLinkedNotebooks = new TreeSet(); - -// setAutoDelete(false); - workQueue=new LinkedBlockingQueue(MAX_QUEUED_WAITING); - } - @Override - public void run() { - errorSharedNotebooks = new Vector(); - errorSharedNotebooksIgnored = new HashMap(); - try { - logger.log(logger.EXTREME, "Starting thread"); - conn = new DatabaseConnection(logger, dburl, indexUrl, resourceUrl, dbuid, dbpswd, dbcpswd, 200); - while(keepRunning) { - logger.log(logger.EXTREME, "Blocking until work is found"); - String work = workQueue.take(); - logger.log(logger.EXTREME, "Work found: " +work); - if (work.equalsIgnoreCase("stop")) { - idle=false; - return; - } - idle=false; - error=false; - if (authRefreshNeeded == true || !isConnected) { - logger.log(logger.EXTREME, "Refreshing connection"); - refreshConnection(); - } - if (syncNeeded) { - logger.log(logger.EXTREME, "SyncNeeded is true"); - refreshNeeded=false; - sequenceDate = conn.getSyncTable().getLastSequenceDate(); - updateSequenceNumber = conn.getSyncTable().getUpdateSequenceNumber(); - try { - logger.log(logger.EXTREME, "Beginning sync"); - evernoteSync(localNoteStore); - logger.log(logger.EXTREME, "Sync finished"); - } catch (UnknownHostException e) { - status.message.emit(e.getMessage()); - } - } - idle=true; - logger.log(logger.EXTREME, "Signaling refresh finished. refreshNeeded=" +refreshNeeded); - syncSignal.finished.emit(refreshNeeded); - if (error) { - syncSignal.errorDisconnect.emit(); - status.message.emit(tr("Error synchronizing - see log for details.")); - } - } - } - catch (InterruptedException e1) { - e1.printStackTrace(); - } - conn.dbShutdown(); - } - - - public DatabaseConnection getConnection() { - return conn; - } - - public boolean isIdle() { - return idle; - } - - - public void setConnected(boolean c) { - isConnected = c; - } - public void setKeepRunning(boolean r) { - logger.log(logger.EXTREME, "Setting keepRunning=" +r); - keepRunning = r; - } - public void setNoteStore(NoteStore.Client c) { - logger.log(logger.EXTREME, "Setting NoteStore in sync thread"); - localNoteStore = c; - } - public void setUserStore(UserStore.Client c) { - logger.log(logger.EXTREME, "Setting UserStore in sync thread"); - userStore = c; - } - - public void setEvernoteUpdateCount(long s) { - logger.log(logger.EXTREME, "Setting Update Count in sync thread"); - evernoteUpdateCount = s; - } - - //*************************************************************** - //*************************************************************** - //** These functions deal with Evernote communications - //*************************************************************** - //*************************************************************** - // Synchronize changes with Evernote - @SuppressWarnings("unused") - private void evernoteSync(Client noteStore) throws java.net.UnknownHostException { - logger.log(logger.HIGH, "Entering SyncRunner.evernoteSync"); - - // Rebuild list of tags & notebooks to ignore - ignoreNotebooks.clear(); - List ignore = conn.getSyncTable().getIgnoreRecords("NOTEBOOK"); - for (int i=0; i sequenceDate) { - logger.log(logger.EXTREME, "Full sequence date has expired"); - sequenceDate = 0; - conn.getSyncTable().setLastSequenceDate(0); - updateSequenceNumber = 0; - conn.getSyncTable().setUpdateSequenceNumber(0); - } - // Check for "special" sync instructions - String syncLinked = conn.getSyncTable().getRecord("FullLinkedNotebookSync"); - String syncShared = conn.getSyncTable().getRecord("FullSharedNotebookSync"); - String syncNotebooks = conn.getSyncTable().getRecord("FullNotebookSync"); - String syncInkNoteImages = conn.getSyncTable().getRecord("FullInkNoteImageSync"); - if (syncLinked != null) { - downloadAllLinkedNotebooks(localNoteStore); - } - if (syncShared != null) { - downloadAllSharedNotebooks(localNoteStore); - } - if (syncNotebooks != null) { - downloadAllNotebooks(localNoteStore); - } - - if (syncInkNoteImages != null) { - List guids = conn.getNoteTable().noteResourceTable.findInkNotes(); - for (int i=0; i updateSequenceNumber) { - logger.log(logger.EXTREME, "Refresh needed is true"); - refreshNeeded = true; - logger.log(logger.EXTREME, "Downloading changes"); - syncRemoteToLocal(localNoteStore); - } - - //***************************************** - //* Sync linked/shared notebooks - //***************************************** - syncLinkedNotebooks(); - - if (!disableUploads) { - logger.log(logger.EXTREME, "Uploading changes"); - // Synchronize remote changes - if (!error) - syncExpunged(localNoteStore); - if (!error) - syncLocalTags(localNoteStore); - if (!error) - syncLocalNotebooks(localNoteStore); - if (!error) - syncLocalLinkedNotebooks(localNoteStore); - if (!error) - syncDeletedNotes(localNoteStore); - if (!error) - syncLocalNotes(); - if (!error) - syncLocalSavedSearches(localNoteStore); - } - - status.message.emit(tr("Cleaning up")); - List notes = conn.getNoteTable().expungeIgnoreSynchronizedNotes(conn.getSyncTable().getIgnoreRecords("NOTEBOOK"), - conn.getSyncTable().getIgnoreRecords("TAG"), conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK")); - if (notes.size() > 0) - syncSignal.refreshLists.emit(); - - //***************************************** - //* End of synchronization - //***************************************** - if (refreshNeeded) - syncSignal.refreshLists.emit(); - - if (!error) { - logger.log(logger.LOW, "Sync completed. Errors=" +error); - if (!disableUploads) - status.message.emit(tr("Synchronizing complete")); - else - status.message.emit(tr("Download syncronization complete. Uploads have been disabled.")); - - logger.log(logger.EXTREME, "Saving sync time"); - if (syncState.getCurrentTime() > sequenceDate) - sequenceDate = syncState.getCurrentTime(); - if (syncState.getUpdateCount() > updateSequenceNumber) - updateSequenceNumber = syncState.getUpdateCount(); - conn.getSyncTable().setLastSequenceDate(sequenceDate); - conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber); - } - } - logger.log(logger.HIGH, "Leaving SyncRunner.evernoteSync"); - } - - // Sync deleted items with Evernote - private void syncExpunged(Client noteStore) { - logger.log(logger.HIGH, "Entering SyncRunner.syncExpunged"); - - List expunged = conn.getDeletedTable().getAllDeleted(); - boolean error = false; - for (int i=0; i errorSharedNotebooks; + public volatile HashMap errorSharedNotebooksIgnored; + public volatile boolean isConnected; + public volatile boolean keepRunning; + public volatile String authToken; + private long evernoteUpdateCount; + private final String userAgent = "NeighborNote/" + System.getProperty("os.name") + +"/"+System.getProperty("java.vendor") + "/" + + System.getProperty("java.version") +";"; + + public volatile NoteStore.Client localNoteStore; + private UserStore.Client userStore; + + public volatile StatusSignal status; + public volatile TagSignal tagSignal; + public volatile NotebookSignal notebookSignal; + public volatile NoteIndexSignal noteIndexSignal; + public volatile NoteSignal noteSignal; + public volatile SavedSearchSignal searchSignal; + public volatile NoteResourceSignal resourceSignal; + public volatile SyncSignal syncSignal; + public volatile LimitSignal limitSignal; + public volatile boolean authRefreshNeeded; + public volatile boolean syncNeeded; + public volatile boolean disableUploads; + public volatile boolean syncDeletedContent; + private volatile List dirtyNoteGuids; + + public volatile String username = ""; + public volatile String password = ""; + public volatile String userStoreUrl; + public String noteStoreUrlBase; + private THttpClient userStoreTrans; + private TBinaryProtocol userStoreProt; + //private AuthenticationResult authResult; + private AuthenticationResult linkedAuthResult; + private User user; +// private long authTimeRemaining; + public long authRefreshTime; + public long failedRefreshes = 0; + public THttpClient noteStoreTrans; + public TBinaryProtocol noteStoreProt; + public String noteStoreUrl; + public long sequenceDate; + public int updateSequenceNumber; + private boolean refreshNeeded; + private volatile LinkedBlockingQueue workQueue; + private static int MAX_QUEUED_WAITING = 1000; + String dbuid; + String dburl; + String indexUrl; + String resourceUrl; + // ICHANGED + String behaviorUrl; + + String dbpswd; + String dbcpswd; + private final TreeSet ignoreTags; + private final TreeSet ignoreNotebooks; + private final TreeSet ignoreLinkedNotebooks; + private HashMap badTagSync; + + + // ICHANGED String bを追加 + public SyncRunner(String logname, String u, String i, String r, String b, String uid, String pswd, String cpswd) { + logger = new ApplicationLogger(logname); + + noteSignal = new NoteSignal(); + status = new StatusSignal(); + tagSignal = new TagSignal(); + notebookSignal = new NotebookSignal(); + noteIndexSignal = new NoteIndexSignal(); + noteSignal = new NoteSignal(); + searchSignal = new SavedSearchSignal(); + syncSignal = new SyncSignal(); + resourceSignal = new NoteResourceSignal(); + limitSignal = new LimitSignal(); + resourceUrl = r; + indexUrl = i; + // ICHANGED + behaviorUrl = b; + + dbuid = uid; + dburl = u; + dbpswd = pswd; + dbcpswd = cpswd; +// this.setAutoDelete(false); + + isConnected = false; + syncNeeded = false; + authRefreshNeeded = false; + keepRunning = true; + idle = true; + disableUploads = false; + ignoreTags = new TreeSet(); + ignoreNotebooks = new TreeSet(); + ignoreLinkedNotebooks = new TreeSet(); + +// setAutoDelete(false); + workQueue=new LinkedBlockingQueue(MAX_QUEUED_WAITING); + } + @Override + public void run() { + errorSharedNotebooks = new ArrayList(); + errorSharedNotebooksIgnored = new HashMap(); + try { + logger.log(logger.EXTREME, "Starting thread"); + // ICHANGED behaviorUrlを追加 + conn = new DatabaseConnection(logger, dburl, indexUrl, resourceUrl, behaviorUrl, dbuid, dbpswd, dbcpswd, 200); + while(keepRunning) { + logger.log(logger.EXTREME, "Blocking until work is found"); + String work = workQueue.take(); + logger.log(logger.LOW, "Dirty Notes Before Sync: " +new Integer(conn.getNoteTable().getDirtyCount()).toString()); + logger.log(logger.EXTREME, "Work found: " +work); + if (work.equalsIgnoreCase("stop")) { + idle=false; + return; + } + conn.getNoteTable().dumpDirtyNotes(); // Debugging statement + idle=false; + error=false; + if (syncNeeded) { + logger.log(logger.EXTREME, "SyncNeeded is true"); + refreshNeeded=false; + sequenceDate = conn.getSyncTable().getLastSequenceDate(); + updateSequenceNumber = conn.getSyncTable().getUpdateSequenceNumber(); + try { + logger.log(logger.EXTREME, "Beginning sync"); + evernoteSync(localNoteStore); + logger.log(logger.EXTREME, "Sync finished"); + } catch (UnknownHostException e) { + status.message.emit(e.getMessage()); + } + } + idle=true; + logger.log(logger.EXTREME, "Signaling refresh finished. refreshNeeded=" +refreshNeeded); + syncSignal.finished.emit(refreshNeeded); + if (error) { + syncSignal.errorDisconnect.emit(); + status.message.emit(tr("Error synchronizing - see log for details.")); + } + logger.log(logger.LOW, "Dirty Notes After Sync: " +new Integer(conn.getNoteTable().getDirtyCount()).toString()); + conn.getNoteTable().dumpDirtyNotes(); + logger.log(logger.LOW, "---"); + } + } + catch (InterruptedException e1) { + e1.printStackTrace(); + } + conn.dbShutdown(); + } + + + public DatabaseConnection getConnection() { + return conn; + } + + public boolean isIdle() { + return idle; + } + + + public void setConnected(boolean c) { + isConnected = c; + } + public void setKeepRunning(boolean r) { + logger.log(logger.EXTREME, "Setting keepRunning=" +r); + keepRunning = r; + } + public void setNoteStore(NoteStore.Client c) { + logger.log(logger.EXTREME, "Setting NoteStore in sync thread"); + localNoteStore = c; + } + public void setUserStore(UserStore.Client c) { + logger.log(logger.EXTREME, "Setting UserStore in sync thread"); + userStore = c; + } + + public void setEvernoteUpdateCount(long s) { + logger.log(logger.EXTREME, "Setting Update Count in sync thread"); + evernoteUpdateCount = s; + } + + //*************************************************************** + //*************************************************************** + //** These functions deal with Evernote communications + //*************************************************************** + //*************************************************************** + // Synchronize changes with Evernote + @SuppressWarnings("unused") + private void evernoteSync(Client noteStore) throws java.net.UnknownHostException { + logger.log(logger.HIGH, "Entering SyncRunner.evernoteSync"); + + // Rebuild list of tags & notebooks to ignore + ignoreNotebooks.clear(); + List ignore = conn.getSyncTable().getIgnoreRecords("NOTEBOOK"); + for (int i=0; i sequenceDate) { + logger.log(logger.EXTREME, "Full sequence date has expired"); + sequenceDate = 0; + conn.getSyncTable().setLastSequenceDate(0); + updateSequenceNumber = 0; + conn.getSyncTable().setUpdateSequenceNumber(0); + } + // Check for "special" sync instructions + String syncLinked = conn.getSyncTable().getRecord("FullLinkedNotebookSync"); + String syncShared = conn.getSyncTable().getRecord("FullSharedNotebookSync"); + String syncNotebooks = conn.getSyncTable().getRecord("FullNotebookSync"); + String syncInkNoteImages = conn.getSyncTable().getRecord("FullInkNoteImageSync"); + if (syncLinked != null) { + downloadAllLinkedNotebooks(localNoteStore); + } + if (syncShared != null) { + downloadAllSharedNotebooks(localNoteStore); + } + if (syncNotebooks != null) { + downloadAllNotebooks(localNoteStore); + } + + if (syncInkNoteImages != null) { + List guids = conn.getNoteTable().noteResourceTable.findInkNotes(); + for (int i=0; i updateSequenceNumber) { + logger.log(logger.EXTREME, "Refresh needed is true"); + refreshNeeded = true; + logger.log(logger.EXTREME, "Downloading changes"); + syncRemoteToLocal(localNoteStore); + } + + //***************************************** + //* Sync linked/shared notebooks + //***************************************** + //syncLinkedNotebooks(); + //conn.getNoteTable().getDirty(); + //disableUploads = true; /// DELETE THIS LINE!!!! + if (!disableUploads) { + logger.log(logger.EXTREME, "Uploading changes"); + // Synchronize remote changes + if (!error) + syncExpunged(localNoteStore); + if (!error) + syncLocalTags(localNoteStore); + if (!error) + syncLocalNotebooks(localNoteStore); + if (!error) + syncLocalLinkedNotebooks(localNoteStore); + if (!error) + syncDeletedNotes(localNoteStore); + if (!error) + syncLocalNotes(); + if (!error) + syncLocalSavedSearches(localNoteStore); + } + + status.message.emit(tr("Cleaning up")); + List notes = conn.getNoteTable().expungeIgnoreSynchronizedNotes(conn.getSyncTable().getIgnoreRecords("NOTEBOOK"), + conn.getSyncTable().getIgnoreRecords("TAG"), conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK")); + if (notes.size() > 0) + syncSignal.refreshLists.emit(); + + //***************************************** + //* End of synchronization + //***************************************** + if (refreshNeeded) + syncSignal.refreshLists.emit(); + + if (!error) { + logger.log(logger.LOW, "Sync completed. Errors=" +error); + if (!disableUploads) + status.message.emit(tr("Synchronizing complete")); + else + status.message.emit(tr("Download syncronization complete. Uploads have been disabled.")); + + logger.log(logger.EXTREME, "Saving sync time"); + if (syncState.getCurrentTime() > sequenceDate) + sequenceDate = syncState.getCurrentTime(); + if (syncState.getUpdateCount() > updateSequenceNumber) + updateSequenceNumber = syncState.getUpdateCount(); + conn.getSyncTable().setLastSequenceDate(sequenceDate); + conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber); + } + } + logger.log(logger.HIGH, "Leaving SyncRunner.evernoteSync"); + } + + // Sync deleted items with Evernote + private void syncExpunged(Client noteStore) { + logger.log(logger.HIGH, "Entering SyncRunner.syncExpunged"); + + List expunged = conn.getDeletedTable().getAllDeleted(); + boolean error = false; + for (int i=0; i notes = conn.getNoteTable().getDirty(); - // Sync the local notebooks with Evernote's - for (int i=0; i 0 && (enNote.isActive() == false || enNote.getDeleted() > 0)) { - if (syncDeletedContent) { - logger.log(logger.EXTREME, "Deleted note found & synch content selected"); - Note delNote = conn.getNoteTable().getNote(enNote.getGuid(), true, true, true, true, true); - delNote = getNoteContent(delNote); - delNote = noteStore.updateNote(authToken, delNote); - enNote.setUpdateSequenceNum(delNote.getUpdateSequenceNum()); - conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum()); - } else { - logger.log(logger.EXTREME, "Deleted note found & sync content not selected"); - int usn = noteStore.deleteNote(authToken, enNote.getGuid()); - enNote.setUpdateSequenceNum(usn); - conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum()); - } - logger.log(logger.EXTREME, "Resetting deleted dirty flag"); - conn.getNoteTable().resetDirtyFlag(enNote.getGuid()); - updateSequenceNumber = enNote.getUpdateSequenceNum(); - logger.log(logger.EXTREME, "Saving sequence number"); - conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber); - } - } catch (EDAMUserException e) { - //logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotes "+e); - //status.message.emit("Error sending local note: " +e.getParameter()); - //logger.log(logger.LOW, e.toString()); - //error = true; - } catch (EDAMSystemException e) { - logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotes "+e); - status.message.emit(tr("Error: ") +e); - logger.log(logger.LOW, e.toString()); - error = true; - } catch (EDAMNotFoundException e) { - //logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalNotes " +e); - //status.message.emit("Error deleting local note: " +e +" - Continuing"); - //logger.log(logger.LOW, e.toString()); - //error = true; - } catch (TException e) { - logger.log(logger.LOW, "*** EDAM TExcepton syncLocalNotes "+e); - status.message.emit(tr("Error sending local note: ") +e); - logger.log(logger.LOW, e.toString()); - error = true; - } - } - } - // Sync notes with Evernote - private void syncLocalNotes() { - logger.log(logger.HIGH, "Entering SyncRunner.syncNotes"); - status.message.emit(tr("Sending local notes.")); - - List notes = conn.getNoteTable().getDirty(); - // Sync the local notebooks with Evernote's - for (int i=0; i 0) { - logger.log(logger.EXTREME, "Active dirty note found - non new" +enNote.getGuid()); - logger.log(logger.EXTREME, "Fetching note content"); - enNote = getNoteContent(enNote); - logger.log(logger.MEDIUM, "Updating note : "+ enNote.getGuid() +" " +enNote.getTitle()+""); - enNote = noteStore.updateNote(token, enNote); - } else { - logger.log(logger.EXTREME, "Active dirty found - new note " +enNote.getGuid()); - String oldGuid = enNote.getGuid(); - logger.log(logger.MEDIUM, "Fetching note content"); - enNote = getNoteContent(enNote); - logger.log(logger.MEDIUM, "Creating note : "+ enNote.getGuid() +" " +enNote.getTitle()+""); - enNote = noteStore.createNote(token, enNote); - logger.log(logger.MEDIUM, "New note Guid : "+ enNote.getGuid() +" " +enNote.getTitle()+""); - noteSignal.guidChanged.emit(oldGuid, enNote.getGuid()); - conn.getNoteTable().updateNoteGuid(oldGuid, enNote.getGuid()); - } - updateSequenceNumber = enNote.getUpdateSequenceNum(); - logger.log(logger.EXTREME, "Saving note"); - conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum()); - List rl = enNote.getResources(); - logger.log(logger.EXTREME, "Getting note resources"); - for (int j=0; j notes = conn.getNoteTable().getDirty(); + // Sync the local notebooks with Evernote's + for (int i=0; i 0 && (enNote.isActive() == false || enNote.getDeleted() > 0)) { + // Check that the note is valid. + if (enNote.isActive() == true || enNote.getDeleted() == 0) { + conn.getNoteTable().deleteNote(enNote.getGuid()); + enNote = conn.getNoteTable().getNote(enNote.getGuid(), false, false, false, false, false); } - } - logger.log(logger.EXTREME, "Resetting note dirty flag"); - conn.getNoteTable().resetDirtyFlag(enNote.getGuid()); - updateSequenceNumber = enNote.getUpdateSequenceNum(); - logger.log(logger.EXTREME, "Emitting note sequence number change"); - conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber); - - } catch (EDAMUserException e) { + if (syncDeletedContent) { + logger.log(logger.EXTREME, "Deleted note found & synch content selected"); + Note delNote = conn.getNoteTable().getNote(enNote.getGuid(), true, true, true, true, true); + delNote = getNoteContent(delNote); + delNote = noteStore.updateNote(authToken, delNote); + enNote.setUpdateSequenceNum(delNote.getUpdateSequenceNum()); + conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum()); + } else { + logger.log(logger.EXTREME, "Deleted note found & sync content not selected"); + int usn = noteStore.deleteNote(authToken, enNote.getGuid()); + enNote.setUpdateSequenceNum(usn); + conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum()); + } + logger.log(logger.EXTREME, "Resetting deleted dirty flag"); + conn.getNoteTable().resetDirtyFlag(enNote.getGuid()); + updateSequenceNumber = enNote.getUpdateSequenceNum(); + logger.log(logger.EXTREME, "Saving sequence number"); + conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber); + } + } catch (EDAMUserException e) { logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotes "+e); - status.message.emit(tr("Error sending local note: ") +e.getParameter()); - logger.log(logger.LOW, e.toString()); - error = true; - } catch (EDAMSystemException e) { - logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotes "+e); - status.message.emit(tr("Error: ") +e); - logger.log(logger.LOW, e.toString()); - error = true; - } catch (EDAMNotFoundException e) { + //status.message.emit("Error sending local note: " +e.getParameter()); + //logger.log(logger.LOW, e.toString()); + //error = true; + } catch (EDAMSystemException e) { + if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) { + limitSignal.rateLimitReached.emit(e.getRateLimitDuration()); + } + logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotes "+e); + status.message.emit(tr("Error: ") +e); + logger.log(logger.LOW, e.toString()); + error = true; + } catch (EDAMNotFoundException e) { logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalNotes " +e); - status.message.emit(tr("Error sending local note: ") +e); - logger.log(logger.LOW, e.toString()); - error = true; - } catch (TException e) { - logger.log(logger.LOW, "*** EDAM TExcepton syncLocalNotes "+e); - status.message.emit(tr("Error sending local note: ") +e); - logger.log(logger.LOW, e.toString()); - error = true; - } - } - logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalNote"); - - } - - // Sync Notebooks with Evernote - private void syncLocalNotebooks(Client noteStore) { - logger.log(logger.HIGH, "Entering SyncRunner.syncLocalNotebooks"); - - status.message.emit(tr("Sending local notebooks.")); - List remoteList = new ArrayList(); - try { - logger.log(logger.EXTREME, "Getting remote notebooks to compare with local"); - remoteList = noteStore.listNotebooks(authToken); - } catch (EDAMUserException e1) { - logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotebooks getting remote Notebook List"); - status.message.emit(tr("Error: ") +e1); - logger.log(logger.LOW, e1.toString()); - error = true; - } catch (EDAMSystemException e1) { - logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotebooks getting remote Notebook List"); - status.message.emit(tr("Error: ") +e1); - logger.log(logger.LOW, e1.toString()); - error = true; - } catch (TException e1) { - logger.log(logger.LOW, "*** EDAM Transaction Excepton syncLocalNotebooks getting remote Notebook List"); - status.message.emit(tr("Error: ") +e1); - logger.log(logger.LOW, e1.toString()); - error = true; - } - logger.log(logger.EXTREME, "Getting local dirty notebooks"); - List notebooks = conn.getNotebookTable().getDirty(); - int sequence; - // Sync the local notebooks with Evernote's - for (int i=0; i 0) { - logger.log(logger.EXTREME, "Existing notebook is dirty"); - sequence = noteStore.updateNotebook(authToken, enNotebook); - } else { - logger.log(logger.EXTREME, "New dirty notebook found"); - String oldGuid = enNotebook.getGuid(); - boolean found = false; - - // Look for a notebook with the same name. If one is found, we don't need - // to create another one - logger.log(logger.EXTREME, "Looking for matching notebook name"); - for (int k=0; k remoteList = new ArrayList(); - status.message.emit(tr("Sending local tags.")); - - try { - logger.log(logger.EXTREME, "Getting remote tags to compare names with the local tags"); - remoteList = noteStore.listTags(authToken); - } catch (EDAMUserException e1) { - logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags getting remote Tag List"); - status.message.emit(tr("Error: ") +e1); - logger.log(logger.LOW, e1.toString()); - error = true; - } catch (EDAMSystemException e1) { - logger.log(logger.LOW, "*** EDAM System Excepton syncLocalTags getting remote Tag List"); - status.message.emit(tr("Error: ") +e1); - logger.log(logger.LOW, e1.toString()); - error = true; - } catch (TException e1) { - logger.log(logger.LOW, "*** EDAM Transaction Excepton syncLocalTags getting remote Tag List"); - status.message.emit(tr("Error: ") +e1); - logger.log(logger.LOW, e1.toString()); - error = true; - } - - int sequence; - - if (badTagSync == null) - badTagSync = new HashMap(); - else - badTagSync.clear(); - - Tag enTag = findNextTag(); - - // This is a hack. Sometimes this function goes flookey and goes into a - // perpetual loop. This causes NeverNote to flood Evernote's servers. - // This is a safety valve to prevent unlimited loops. - int maxCount = conn.getTagTable().getDirty().size()+10; - int loopCount = 0; - - while(enTag!=null && loopCount < maxCount) { - loopCount++; - if (authRefreshNeeded) - if (!refreshConnection()) - return; + //status.message.emit("Error deleting local note: " +e +" - Continuing"); + //logger.log(logger.LOW, e.toString()); + //error = true; + } catch (TException e) { + logger.log(logger.LOW, "*** EDAM TExcepton syncLocalNotes "+e); + status.message.emit(tr("Error sending local note: ") +e); + logger.log(logger.LOW, e.toString()); + error = true; + } + } + } + // Sync notes with Evernote + private void syncLocalNotes() { + logger.log(logger.HIGH, "Entering SyncRunner.syncNotes"); + logger.log(logger.LOW, "Dirty local notes found: " +new Integer(conn.getNoteTable().getDirtyCount()).toString()); + status.message.emit(tr("Sending local notes.")); + + List notes = conn.getNoteTable().getDirty(); + // Sync the local notebooks with Evernote's + for (int i=0; i 0) { + logger.log(logger.EXTREME, "Active dirty note found - non new - " +enNote.getGuid()); + logger.log(logger.EXTREME, "Fetching note content"); + enNote = getNoteContent(enNote); + logger.log(logger.MEDIUM, "Updating note : "+ enNote.getGuid() +" " +enNote.getTitle()+""); + enNote = noteStore.updateNote(token, enNote); + } else { + logger.log(logger.EXTREME, "Active dirty found - new note " +enNote.getGuid()); + String oldGuid = enNote.getGuid(); + logger.log(logger.MEDIUM, "Fetching note content"); + enNote = getNoteContent(enNote); + logger.log(logger.MEDIUM, "Creating note : "+ enNote.getGuid() +" " +enNote.getTitle()+""); + enNote = noteStore.createNote(token, enNote); + logger.log(logger.MEDIUM, "New note Guid : "+ enNote.getGuid() +" " +enNote.getTitle()+""); + noteSignal.guidChanged.emit(oldGuid, enNote.getGuid()); + conn.getNoteTable().updateNoteGuid(oldGuid, enNote.getGuid()); + } + updateSequenceNumber = enNote.getUpdateSequenceNum(); + logger.log(logger.EXTREME, "Saving note"); + conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum()); + List rl = enNote.getResources(); + logger.log(logger.EXTREME, "Getting note resources"); + for (int j=0; j remoteList = new ArrayList(); + try { + logger.log(logger.EXTREME, "Getting remote notebooks to compare with local"); + remoteList = noteStore.listNotebooks(authToken); + } catch (EDAMUserException e1) { + logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotebooks getting remote Notebook List"); + status.message.emit(tr("Error: ") +e1); + logger.log(logger.LOW, e1.toString()); + error = true; + } catch (EDAMSystemException e1) { + if (e1.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) { + limitSignal.rateLimitReached.emit(e1.getRateLimitDuration()); + } + logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotebooks getting remote Notebook List"); + status.message.emit(tr("Error: ") +e1); + logger.log(logger.LOW, e1.toString()); + error = true; + } catch (TException e1) { + logger.log(logger.LOW, "*** EDAM Transaction Excepton syncLocalNotebooks getting remote Notebook List"); + status.message.emit(tr("Error: ") +e1); + logger.log(logger.LOW, e1.toString()); + error = true; + } + logger.log(logger.EXTREME, "Getting local dirty notebooks"); + List notebooks = conn.getNotebookTable().getDirty(); + int sequence; + // Sync the local notebooks with Evernote's + for (int i=0; i 0) { + logger.log(logger.EXTREME, "Existing notebook is dirty"); + sequence = noteStore.updateNotebook(authToken, enNotebook); + } else { + logger.log(logger.EXTREME, "New dirty notebook found"); + String oldGuid = enNotebook.getGuid(); + boolean found = false; + + // Look for a notebook with the same name. If one is found, we don't need + // to create another one + logger.log(logger.EXTREME, "Looking for matching notebook name"); + for (int k=0; k remoteList = new ArrayList(); + status.message.emit(tr("Sending local tags.")); + + try { + logger.log(logger.EXTREME, "Getting remote tags to compare names with the local tags"); + remoteList = noteStore.listTags(authToken); + } catch (EDAMUserException e1) { + logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags getting remote Tag List"); + status.message.emit(tr("Error: ") +e1); + logger.log(logger.LOW, e1.toString()); + error = true; + } catch (EDAMSystemException e1) { + if (e1.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) { + limitSignal.rateLimitReached.emit(e1.getRateLimitDuration()); + } + logger.log(logger.LOW, "*** EDAM System Excepton syncLocalTags getting remote Tag List"); + status.message.emit(tr("Error: ") +e1); + logger.log(logger.LOW, e1.toString()); + error = true; + } catch (TException e1) { + logger.log(logger.LOW, "*** EDAM Transaction Excepton syncLocalTags getting remote Tag List"); + status.message.emit(tr("Error: ") +e1); + logger.log(logger.LOW, e1.toString()); + error = true; + } + + int sequence; + + if (badTagSync == null) + badTagSync = new HashMap(); + else + badTagSync.clear(); + + Tag enTag = findNextTag(); + + // This is a hack. Sometimes this function goes flookey and goes into a + // perpetual loop. This causes NeverNote to flood Evernote's servers. + // This is a safety valve to prevent unlimited loops. + int maxCount = conn.getTagTable().getDirty().size()+10; + int loopCount = 0; + + while(enTag!=null && loopCount < maxCount) { + loopCount++; +// if (authRefreshNeeded) +// if (!refreshConnection()) +// return; + + try { + if (enTag.getUpdateSequenceNum() > 0) { + logger.log(logger.EXTREME, "Updating tag"); + sequence = noteStore.updateTag(authToken, enTag); + } else { + + // Look for a tag with the same name. If one is found, we don't need + // to create another one + logger.log(logger.EXTREME, "New tag. Comparing with remote names"); + boolean found = false; + String oldGuid = enTag.getGuid(); + for (int k=0; k list = conn.getLinkedNotebookTable().getDirtyGuids(); + for (int i=0; i remoteList = new ArrayList(); + status.message.emit(tr("Sending saved searches.")); + + logger.log(logger.EXTREME, "Getting saved searches to compare with local"); + try { + remoteList = noteStore.listSearches(authToken); + } catch (EDAMUserException e1) { + logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags getting remote saved search List"); + status.message.emit(tr("Error: ") +e1); + logger.log(logger.LOW, e1.toString()); + error = true; + } catch (EDAMSystemException e1) { + if (e1.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) { + limitSignal.rateLimitReached.emit(e1.getRateLimitDuration()); + } + logger.log(logger.LOW, "*** EDAM System Excepton syncLocalTags getting remote saved search List"); + status.message.emit(tr("Error: ") +e1); + logger.log(logger.LOW, e1.toString()); + error = true; + } catch (TException e1) { + logger.log(logger.LOW, "*** EDAM Transaction Excepton syncLocalTags getting remote saved search List"); + status.message.emit(tr("Error: ") +e1); + logger.log(logger.LOW, e1.toString()); + error = true; + } + + List searches = conn.getSavedSearchTable().getDirty(); + int sequence; + // Sync the local notebooks with Evernote's + logger.log(logger.EXTREME, "Beginning to send saved searches"); + for (int i=0; i 0) + sequence = noteStore.updateSearch(authToken, enSearch); + else { + logger.log(logger.EXTREME, "New saved search found."); + // Look for a tag with the same name. If one is found, we don't need + // to create another one + boolean found = false; + logger.log(logger.EXTREME, "Matching remote saved search names with local"); + for (int k=0; k dirtyNotes = conn.getNoteTable().getDirty(); + dirtyNoteGuids = new ArrayList(); + for (int i=0; i 0 && keepRunning) { + logger.log(logger.EXTREME, "emitting sequence number to main thread"); + updateSequenceNumber = chunk.getChunkHighUSN(); + conn.getSyncTable().setLastSequenceDate(chunk.getCurrentTime()); + conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber); +// conn.commitTransaction(); + } + + + if (more) { + long pct = chunk.getChunkHighUSN() * 100; + conn.getSyncTable().setLastSequenceDate(chunk.getCurrentTime()); + pct = pct/evernoteUpdateCount; + status.message.emit(tr("Downloading ") +new Long(pct).toString()+tr("% complete.")); + } +// conn.commitTransaction(); + } + logger.log(logger.HIGH, "Leaving SyncRunner.syncRemoteToLocal"); + } + // Sync expunged notes + private void syncExpungedNotes(SyncChunk chunk) { + // Do the local deletes + logger.log(logger.EXTREME, "Doing local deletes"); + List guid = chunk.getExpungedNotes(); + if (guid != null) { + for (int i=0; i tags) { + logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteTags"); + if (tags != null) { + for (int i=0; i searches) { + logger.log(logger.EXTREME, "Entering SyncRunner.syncSavedSearches"); + if (searches != null) { + for (int i=0; i books) { + logger.log(logger.EXTREME, "Entering SyncRunner.syncLinkedNotebooks"); + if (books != null) { + for (int i=0; i notebooks) { + logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotebooks"); + if (notebooks != null) { + for (int i=0; i 0) { +// conn.getSharedNotebookTable().expungeNotebookByGuid(notebooks.get(i).getGuid(), false); +// for (int j=0; j books = noteStore.getSharedNotebookByAuth(authToken); +// } + // Sync remote Resources + private void syncRemoteResources(Client noteStore, List resource) { + logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteResources"); + if (resource != null) { + for (int i=0; i note, boolean fullSync, String token) { - try { - if (enTag.getUpdateSequenceNum() > 0) { - logger.log(logger.EXTREME, "Updating tag"); - sequence = noteStore.updateTag(authToken, enTag); - } else { - - // Look for a tag with the same name. If one is found, we don't need - // to create another one - logger.log(logger.EXTREME, "New tag. Comparing with remote names"); - boolean found = false; - String oldGuid = enTag.getGuid(); - for (int k=0; k list = conn.getLinkedNotebookTable().getDirtyGuids(); - for (int i=0; i remoteList = new ArrayList(); - status.message.emit(tr("Sending saved searches.")); - - logger.log(logger.EXTREME, "Getting saved searches to compare with local"); - try { - remoteList = noteStore.listSearches(authToken); - } catch (EDAMUserException e1) { - logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags getting remote saved search List"); - status.message.emit(tr("Error: ") +e1); - logger.log(logger.LOW, e1.toString()); - error = true; - } catch (EDAMSystemException e1) { - logger.log(logger.LOW, "*** EDAM System Excepton syncLocalTags getting remote saved search List"); - status.message.emit(tr("Error: ") +e1); - logger.log(logger.LOW, e1.toString()); - error = true; - } catch (TException e1) { - logger.log(logger.LOW, "*** EDAM Transaction Excepton syncLocalTags getting remote saved search List"); - status.message.emit(tr("Error: ") +e1); - logger.log(logger.LOW, e1.toString()); - error = true; - } - - List searches = conn.getSavedSearchTable().getDirty(); - int sequence; - // Sync the local notebooks with Evernote's - logger.log(logger.EXTREME, "Beginning to send saved searches"); - for (int i=0; i 0) - sequence = noteStore.updateSearch(authToken, enSearch); - else { - logger.log(logger.EXTREME, "New saved search found."); - // Look for a tag with the same name. If one is found, we don't need - // to create another one - boolean found = false; - logger.log(logger.EXTREME, "Matching remote saved search names with local"); - for (int k=0; k dirtyNotes = conn.getNoteTable().getDirty(); - dirtyNoteGuids = new Vector(); - for (int i=0; i 0 && keepRunning) { - logger.log(logger.EXTREME, "emitting sequence number to main thread"); - updateSequenceNumber = chunk.getChunkHighUSN(); - conn.getSyncTable().setLastSequenceDate(chunk.getCurrentTime()); - conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber); -// conn.commitTransaction(); - } - - - if (more) { - long pct = chunk.getChunkHighUSN() * 100; - conn.getSyncTable().setLastSequenceDate(chunk.getCurrentTime()); - pct = pct/evernoteUpdateCount; - status.message.emit(tr("Downloading ") +new Long(pct).toString()+tr("% complete.")); - } -// conn.commitTransaction(); - } - logger.log(logger.HIGH, "Leaving SyncRunner.syncRemoteToLocal"); - } - // Sync expunged notes - private void syncExpungedNotes(SyncChunk chunk) { - // Do the local deletes - logger.log(logger.EXTREME, "Doing local deletes"); - List guid = chunk.getExpungedNotes(); - if (guid != null) { - for (int i=0; i tags) { - logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteTags"); - if (tags != null) { - for (int i=0; i searches) { - logger.log(logger.EXTREME, "Entering SyncRunner.syncSavedSearches"); - if (searches != null) { - for (int i=0; i books) { - logger.log(logger.EXTREME, "Entering SyncRunner.syncLinkedNotebooks"); - if (books != null) { - for (int i=0; i notebooks) { - logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotebooks"); - if (notebooks != null) { - for (int i=0; i 0) { -// conn.getSharedNotebookTable().expungeNotebookByGuid(notebooks.get(i).getGuid(), false); -// for (int j=0; j books = noteStore.getSharedNotebookByAuth(authToken); -// } - // Sync remote Resources - private void syncRemoteResources(Client noteStore, List resource) { - logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteResources"); - if (resource != null) { - for (int i=0; i note, boolean fullSync, String token) { - logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotes"); - if (note != null) { - for (int i=0; i books = conn.getNotebookTable().getAllLocal(); - String notebookGuid = null; - for (int i=0; i>> 4) & 0x0F; - int two_halfs = 0; - do { - if ((0 <= halfbyte) && (halfbyte <= 9)) - buf.append((char) ('0' + halfbyte)); - else - buf.append((char) ('a' + (halfbyte - 10))); - halfbyte = element & 0x0F; - } while(two_halfs++ < 1); - } - return buf.toString(); - } - - - - //******************************************************* - //* Find dirty tags, which do not have newly created parents - //******************************************************* - private Tag findNextTag() { - logger.log(logger.HIGH, "Entering SyncRunner.findNextTag"); - Tag nextTag = null; - List tags = conn.getTagTable().getDirty(); - - // Find the parent. If the parent has a sequence > 0 then it is a good - // parent. - for (int i=0; i 0) { - logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - tag found"); - return tags.get(i); - } - } - } - - logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - no tags returned"); - return nextTag; - } - - - // Connect to Evernote - public boolean enConnect() { - try { - userStoreTrans = new THttpClient(userStoreUrl); - userStoreTrans.setCustomHeader("User-Agent", userAgent); - } catch (TTransportException e) { - QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage()); - mb.exec(); - e.printStackTrace(); - } - userStoreProt = new TBinaryProtocol(userStoreTrans); - userStore = new UserStore.Client(userStoreProt, userStoreProt); - syncSignal.saveUserStore.emit(userStore); - try { - authResult = userStore.authenticate(username, password, consumerKey, consumerSecret); - } catch (EDAMUserException e) { - QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Error", "Incorrect username/password"); + } + boolean oldIsDirty = conn.getNoteTable().isNoteDirty(n.getGuid()); + if (!oldIsDirty) + return false; + return true; + } + + private void moveConflictingNote(String guid) { + logger.log(logger.EXTREME, "Conflicting change found for note " +guid); + List books = conn.getNotebookTable().getAllLocal(); + String notebookGuid = null; + for (int i=0; i>> 4) & 0x0F; + int two_halfs = 0; + do { + if ((0 <= halfbyte) && (halfbyte <= 9)) + buf.append((char) ('0' + halfbyte)); + else + buf.append((char) ('a' + (halfbyte - 10))); + halfbyte = element & 0x0F; + } while(two_halfs++ < 1); + } + return buf.toString(); + } + + + + //******************************************************* + //* Find dirty tags, which do not have newly created parents + //******************************************************* + private Tag findNextTag() { + logger.log(logger.HIGH, "Entering SyncRunner.findNextTag"); + Tag nextTag = null; + List tags = conn.getTagTable().getDirty(); + + // Find the parent. If the parent has a sequence > 0 then it is a good + // parent. + for (int i=0; i 0) { + logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - tag found"); + return tags.get(i); + } + } + } + + logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - no tags returned"); + return nextTag; + } + + + // Connect to Evernote + public boolean enConnect() { + try { + userStoreTrans = new THttpClient(userStoreUrl); + userStoreTrans.setCustomHeader("User-Agent", userAgent); + } catch (TTransportException e) { + QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage()); + mb.exec(); + e.printStackTrace(); + } + userStoreProt = new TBinaryProtocol(userStoreTrans); + userStore = new UserStore.Client(userStoreProt, userStoreProt); + + syncSignal.saveUserStore.emit(userStore); + try { + //authResult = userStore.authenticate(username, password, consumerKey, consumerSecret); + user = userStore.getUser(authToken); + } catch (EDAMUserException e) { + QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Error", "Invalid Authorization"); + mb.exec(); + isConnected = false; + return false; + } catch (EDAMSystemException e) { + if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) { + limitSignal.rateLimitReached.emit(e.getRateLimitDuration()); + } + QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "EDAM System Excepton", e.getLocalizedMessage()); + mb.exec(); + e.printStackTrace(); + isConnected = false; + } catch (TException e) { + QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage()); + mb.exec(); + e.printStackTrace(); + isConnected = false; + } + + boolean versionOk = false; + try { + versionOk = userStore.checkVersion("NeighborNote", + com.evernote.edam.userstore.Constants.EDAM_VERSION_MAJOR, + com.evernote.edam.userstore.Constants.EDAM_VERSION_MINOR); + } catch (TException e) { + e.printStackTrace(); + isConnected = false; + } + if (!versionOk) { + System.err.println("Incomatible EDAM client protocol version"); + isConnected = false; + } + //if (authResult != null) { + //user = authResult.getUser(); + //authToken = authResult.getAuthenticationToken(); + if (user == null || noteStoreUrlBase == null) { + logger.log(logger.LOW, "Error retrieving user information. Aborting."); + System.err.println("Error retrieving user information."); + isConnected = false; + QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, tr("Connection Error"), tr("Error retrieving user information. Synchronization not complete")); mb.exec(); - isConnected = false; return false; - } catch (EDAMSystemException e) { - QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "EDAM System Excepton", e.getLocalizedMessage()); - mb.exec(); - e.printStackTrace(); - isConnected = false; - } catch (TException e) { - QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage()); - mb.exec(); - e.printStackTrace(); - isConnected = false; - } - - boolean versionOk = false; - try { - versionOk = userStore.checkVersion("NixNote", - com.evernote.edam.userstore.Constants.EDAM_VERSION_MAJOR, - com.evernote.edam.userstore.Constants.EDAM_VERSION_MINOR); - } catch (TException e) { - e.printStackTrace(); - isConnected = false; - } - if (!versionOk) { - System.err.println("Incomatible EDAM client protocol version"); - isConnected = false; - } - if (authResult != null) { - user = authResult.getUser(); - authToken = authResult.getAuthenticationToken(); - noteStoreUrl = noteStoreUrlBase + user.getShardId(); - syncSignal.saveAuthToken.emit(authToken); - syncSignal.saveNoteStore.emit(localNoteStore); - - try { - noteStoreTrans = new THttpClient(noteStoreUrl); - noteStoreTrans.setCustomHeader("User-Agent", userAgent); - } catch (TTransportException e) { - QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage()); - mb.exec(); - e.printStackTrace(); - isConnected = false; - } - noteStoreProt = new TBinaryProtocol(noteStoreTrans); - localNoteStore = - new NoteStore.Client(noteStoreProt, noteStoreProt); - isConnected = true; - authTimeRemaining = authResult.getExpiration() - authResult.getCurrentTime(); - authRefreshTime = authTimeRemaining / 2; } - - // Get user information - try { - User user = userStore.getUser(authToken); - syncSignal.saveUserInformation.emit(user); - } catch (EDAMUserException e1) { - e1.printStackTrace(); - } catch (EDAMSystemException e1) { - e1.printStackTrace(); - } catch (TException e1) { - e1.printStackTrace(); - } - - return isConnected; - } - // Disconnect from the database - public void enDisconnect() { - isConnected = false; - } - // Refresh the connection - private synchronized boolean refreshConnection() { - logger.log(logger.EXTREME, "Entering SyncRunner.refreshConnection()"); -// Calendar cal = Calendar.getInstance(); - - // If we are not connected let's get out of here - if (!isConnected) - return false; - - // If we fail too many times, then let's give up. - if (failedRefreshes >=5) { - logger.log(logger.EXTREME, "Refresh attempts have failed. Disconnecting."); - isConnected = false; - status.message.emit(tr("Unable to synchronize - Authentication failed")); - return false; - } - - // If this is the first time through, then we need to set this -// if (authRefreshTime == 0 || cal.getTimeInMillis() > authRefreshTime) -// authRefreshTime = cal.getTimeInMillis(); - - // // Default to checking again in 5 min. This in case we fail. - // authRefreshTime = authRefreshTime +(5*60*1000); - - // Try to get a new token - AuthenticationResult newAuth = null; - logger.log(logger.EXTREME, "Beginning to try authentication refresh"); - try { - if (userStore != null && authToken != null) - newAuth = userStore.refreshAuthentication(authToken); - else - return false; - logger.log(logger.EXTREME, "UserStore.refreshAuthentication has succeeded."); - } catch (EDAMUserException e) { - e.printStackTrace(); - syncSignal.authRefreshComplete.emit(false); - failedRefreshes++; - return false; - } catch (EDAMSystemException e) { - e.printStackTrace(); - syncSignal.authRefreshComplete.emit(false); - failedRefreshes++; - return false; - } catch (TException e) { - e.printStackTrace(); - syncSignal.authRefreshComplete.emit(false); - failedRefreshes++; - return false; - } - - // If we didn't get a good auth, then we've failed - if (newAuth == null) { - failedRefreshes++; - status.message.emit(tr("Unable to synchronize - Authentication failed")); - logger.log(logger.EXTREME, "Authentication failure #" +failedRefreshes); - status.message.emit(tr("Unable to synchronize - Authentication failed")); - syncSignal.authRefreshComplete.emit(false); - return false; - } - - // We got a good token. Now we need to setup the time to renew it. - logger.log(logger.EXTREME, "Saving authentication tokens"); - authResult = newAuth; - authToken = new String(newAuth.getAuthenticationToken()); -// authTimeRemaining = authResult.getExpiration() - authResult.getCurrentTime(); -// authRefreshTime = cal.getTimeInMillis() + (authTimeRemaining/4); - failedRefreshes=0; - syncSignal.authRefreshComplete.emit(true); - authRefreshNeeded = false; - - // This should never happen, but if it does we consider this a faild attempt. -// if (authTimeRemaining <= 0) { -// failedRefreshes++; -// syncSignal.authRefreshComplete.emit(false); -// } - - return true; - } - - public synchronized boolean addWork(String request) { - if (workQueue.offer(request)) - return true; - return false; - } - - private Note getNoteContent(Note n) { - QTextCodec codec = QTextCodec.codecForLocale(); - codec = QTextCodec.codecForName("UTF-8"); - n.setContent(codec.toUnicode(new QByteArray(n.getContent()))); - return n; - } - - - - //********************************************************* - //* Special download instructions. Used for DB upgrades - //********************************************************* - private void downloadAllSharedNotebooks(Client noteStore) { - try { - List books = noteStore.listSharedNotebooks(authToken); - logger.log(logger.LOW, "Shared notebooks found = " +books.size()); - for (int i=0; i books = noteStore.listNotebooks(authToken); - logger.log(logger.LOW, "Shared notebooks found = " +books.size()); - for (int i=0; i books = noteStore.listLinkedNotebooks(authToken); - logger.log(logger.LOW, "Linked notebooks found = " +books.size()); - for (int i=0; i nvps = new ArrayList (); - nvps.add(new BasicNameValuePair("auth", authToken)); - - try { - post.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } - try { - HttpResponse response = http.execute(post); - HttpEntity resEntity = response.getEntity(); - InputStream is = resEntity.getContent(); - QByteArray data = writeToFile(is); - conn.getInkImagesTable().saveImage(guid, slice, data); - } catch (ClientProtocolException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - slice++; - } - http.getConnectionManager().shutdown(); - noteSignal.noteChanged.emit(r.getNoteGuid(), null); // Signal to ivalidate note cache - } - - - public QByteArray writeToFile(InputStream iStream) throws IOException { - - File temp = File.createTempFile("nn-inknote-temp", ".png"); - - // Save InputStream to the file. - BufferedOutputStream fOut = null; - try { - fOut = new BufferedOutputStream(new FileOutputStream(temp)); - byte[] buffer = new byte[32 * 1024]; - int bytesRead = 0; - while ((bytesRead = iStream.read(buffer)) != -1) { - fOut.write(buffer, 0, bytesRead); - } - } - finally { - iStream.close(); - fOut.close(); - } - QFile tempFile = new QFile(temp.getAbsoluteFile().toString()); - tempFile.open(OpenModeFlag.ReadOnly); - QByteArray data = tempFile.readAll(); - tempFile.close(); - tempFile.remove(); - return data; - } - - - //****************************************** - //* Begin syncing shared notebooks - //****************************************** - private void syncLinkedNotebooks() { - logger.log(logger.MEDIUM, "Authenticating Shared Notebooks"); - status.message.emit(tr("Synchronizing shared notebooks.")); - List books = conn.getLinkedNotebookTable().getAll(); - - errorSharedNotebooks.clear(); - - for (int i=0; i lastSequenceNumber) { - if (lastSyncDate < linkedSyncState.getFullSyncBefore()) { - lastSequenceNumber = 0; - } - syncLinkedNotebook(linkedNoteStore, books.get(i), - //lastSequenceNumber, linkedSyncState.getUpdateCount(), linkedAuthResult.getAuthenticationToken()); - lastSequenceNumber, linkedSyncState.getUpdateCount(), authToken); - } - - // Synchronize local changes - syncLocalLinkedNoteChanges(linkedNoteStore, books.get(i)); - - } catch (EDAMUserException e) { - e.printStackTrace(); - } catch (EDAMNotFoundException e) { - status.message.emit(tr("Error synchronizing \" " + - books.get(i).getShareName()+"\". Please verify you still have access to that shared notebook.")); - errorSharedNotebooks.add(books.get(i).getGuid()); - errorSharedNotebooksIgnored.put(books.get(i).getGuid(), books.get(i).getGuid()); - logger.log(logger.LOW, "Error synchronizing shared notebook. EDAMNotFound: "+e.getMessage()); - logger.log(logger.LOW, e.getStackTrace()); - error = true; - e.printStackTrace(); - } catch (EDAMSystemException e) { - error = true; - logger.log(logger.LOW, "System error authenticating against shared notebook. "+ - "Key: "+books.get(i).getShareKey() +" Error:" +e.getMessage()); - e.printStackTrace(); - } catch (TException e) { - error = true; - e.printStackTrace(); - } - } - - // Cleanup tags - conn.getTagTable().removeUnusedLinkedTags(); - conn.getTagTable().cleanupTags(); - tagSignal.listChanged.emit(); - return; - } - - - //************************************************************** - //* Linked notebook contents (from someone else's account) - //************************************************************* - private void syncLinkedNotebook(Client linkedNoteStore, LinkedNotebook book, int usn, int highSequence, String token) { - logger.log(logger.EXTREME, "Entering syncLinkedNotebook"); - if (ignoreLinkedNotebooks.contains(book.getGuid())) - return; - List dirtyNotes = conn.getNoteTable().getDirtyLinkedNotes(); - if (dirtyNoteGuids == null) - dirtyNoteGuids = new Vector(); - - for (int i=0; i tags, String notebookGuid) { - logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteTags"); - if (tags != null) { - for (int i=0; i notebooks, boolean readOnly, LinkedNotebook linked) { - logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotebooks"); - if (notebooks != null) { - for (int i=0; i newNotes, String token) { - if (newNotes == null) - return; - for (int i=0; i notes = conn.getNoteTable().getDirtyLinked(notebookGuid); - for (int i=0; i=5) { + logger.log(logger.EXTREME, "Refresh attempts have failed. Disconnecting."); + isConnected = false; + status.message.emit(tr("Unable to synchronize - Authentication failed")); + return false; + } + + // If this is the first time through, then we need to set this +// if (authRefreshTime == 0 || cal.getTimeInMillis() > authRefreshTime) +// authRefreshTime = cal.getTimeInMillis(); + + // // Default to checking again in 5 min. This in case we fail. + // authRefreshTime = authRefreshTime +(5*60*1000); + + // Try to get a new token + AuthenticationResult newAuth = null; + logger.log(logger.EXTREME, "Beginning to try authentication refresh"); + try { + if (userStore != null && authToken != null) + newAuth = userStore.refreshAuthentication(authToken); + else + return false; + logger.log(logger.EXTREME, "UserStore.refreshAuthentication has succeeded."); + } catch (EDAMUserException e) { + e.printStackTrace(); + syncSignal.authRefreshComplete.emit(false); + failedRefreshes++; + return false; + } catch (EDAMSystemException e) { + e.printStackTrace(); + syncSignal.authRefreshComplete.emit(false); + failedRefreshes++; + return false; + } catch (TException e) { + e.printStackTrace(); + syncSignal.authRefreshComplete.emit(false); + failedRefreshes++; + return false; + } + + // If we didn't get a good auth, then we've failed + if (newAuth == null) { + failedRefreshes++; + status.message.emit(tr("Unable to synchronize - Authentication failed")); + logger.log(logger.EXTREME, "Authentication failure #" +failedRefreshes); + status.message.emit(tr("Unable to synchronize - Authentication failed")); + syncSignal.authRefreshComplete.emit(false); + return false; + } + + // We got a good token. Now we need to setup the time to renew it. + logger.log(logger.EXTREME, "Saving authentication tokens"); + authResult = newAuth; + authToken = new String(newAuth.getAuthenticationToken()); +// authTimeRemaining = authResult.getExpiration() - authResult.getCurrentTime(); +// authRefreshTime = cal.getTimeInMillis() + (authTimeRemaining/4); + failedRefreshes=0; + syncSignal.authRefreshComplete.emit(true); + authRefreshNeeded = false; + + // This should never happen, but if it does we consider this a faild attempt. +// if (authTimeRemaining <= 0) { +// failedRefreshes++; +// syncSignal.authRefreshComplete.emit(false); +// } + + return true; + } + + */ + + public synchronized boolean addWork(String request) { + if (workQueue.offer(request)) + return true; + return false; + } + + private Note getNoteContent(Note n) { + QTextCodec codec = QTextCodec.codecForLocale(); + codec = QTextCodec.codecForName("UTF-8"); + n.setContent(codec.toUnicode(new QByteArray(n.getContent()))); + return n; + } + + + + //********************************************************* + //* Special download instructions. Used for DB upgrades + //********************************************************* + private void downloadAllSharedNotebooks(Client noteStore) { + try { + List books = noteStore.listSharedNotebooks(authToken); + logger.log(logger.LOW, "Shared notebooks found = " +books.size()); + for (int i=0; i books = noteStore.listNotebooks(authToken); + logger.log(logger.LOW, "Shared notebooks found = " +books.size()); + for (int i=0; i books = noteStore.listLinkedNotebooks(authToken); + logger.log(logger.LOW, "Linked notebooks found = " +books.size()); + for (int i=0; i nvps = new ArrayList (); + nvps.add(new BasicNameValuePair("auth", authToken)); + + try { + post.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); + } catch (UnsupportedEncodingException e1) { + e1.printStackTrace(); + } + try { + HttpResponse response = http.execute(post); + HttpEntity resEntity = response.getEntity(); + InputStream is = resEntity.getContent(); + QByteArray data = writeToFile(is); + conn.getInkImagesTable().saveImage(guid, slice, data); + } catch (ClientProtocolException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + slice++; + } + http.getConnectionManager().shutdown(); + noteSignal.noteChanged.emit(r.getNoteGuid(), null); // Signal to ivalidate note cache + } + + + public QByteArray writeToFile(InputStream iStream) throws IOException { + + File temp = File.createTempFile("nn-inknote-temp", ".png"); + + // Save InputStream to the file. + BufferedOutputStream fOut = null; + try { + fOut = new BufferedOutputStream(new FileOutputStream(temp)); + byte[] buffer = new byte[32 * 1024]; + int bytesRead = 0; + while ((bytesRead = iStream.read(buffer)) != -1) { + fOut.write(buffer, 0, bytesRead); + } + } + finally { + iStream.close(); + fOut.close(); + } + QFile tempFile = new QFile(temp.getAbsoluteFile().toString()); + tempFile.open(OpenModeFlag.ReadOnly); + QByteArray data = tempFile.readAll(); + tempFile.close(); + tempFile.remove(); + return data; + } + + + //****************************************** + //* Begin syncing shared notebooks + //****************************************** + private void syncLinkedNotebooks() { + logger.log(logger.MEDIUM, "Authenticating linked Notebooks"); + status.message.emit(tr("Synchronizing shared notebooks.")); + List books = conn.getLinkedNotebookTable().getAll(); + + errorSharedNotebooks.clear(); + + for (int i=0; i lastSequenceNumber) { + logger.log(logger.EXTREME, "Remote changes found"); + if (lastSyncDate < linkedSyncState.getFullSyncBefore()) { + lastSequenceNumber = 0; + } + logger.log(logger.EXTREME, "Calling syncLinkedNotebook for " +books.get(i).getShareName()); + syncLinkedNotebook(linkedNoteStore, books.get(i), + lastSequenceNumber, linkedSyncState.getUpdateCount(), authToken); + } + + // Synchronize local changes + syncLocalLinkedNoteChanges(linkedNoteStore, books.get(i)); + + } catch (EDAMUserException e) { + e.printStackTrace(); + } catch (EDAMNotFoundException e) { + status.message.emit(tr("Error synchronizing \" " + + books.get(i).getShareName()+"\". Please verify you still have access to that shared notebook.")); + errorSharedNotebooks.add(books.get(i).getGuid()); + errorSharedNotebooksIgnored.put(books.get(i).getGuid(), books.get(i).getGuid()); + logger.log(logger.LOW, "Error synchronizing shared notebook. EDAMNotFound: "+e.getMessage()); + logger.log(logger.LOW, e.getStackTrace()); + error = true; + e.printStackTrace(); + } catch (EDAMSystemException e) { + if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) { + limitSignal.rateLimitReached.emit(e.getRateLimitDuration()); + } + error = true; + logger.log(logger.LOW, "System error authenticating against shared notebook. "+ + "Key: "+books.get(i).getShareKey() +" Error:" +e.getMessage()); + e.printStackTrace(); + } catch (TException e) { + error = true; + e.printStackTrace(); + } + } + + // Cleanup tags + conn.getTagTable().removeUnusedLinkedTags(); + conn.getTagTable().cleanupTags(); + tagSignal.listChanged.emit(); + return; + } + + + //************************************************************** + //* Linked notebook contents (from someone else's account) + //************************************************************* + private void syncLinkedNotebook(Client linkedNoteStore, LinkedNotebook book, int usn, int highSequence, String token) { + logger.log(logger.EXTREME, "Entering syncLinkedNotebook"); + if (ignoreLinkedNotebooks.contains(book.getGuid())) + return; + List dirtyNotes = conn.getNoteTable().getDirtyLinkedNotes(); + if (dirtyNoteGuids == null) + dirtyNoteGuids = new ArrayList(); + + for (int i=0; i tags, String notebookGuid) { + logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteTags"); + if (tags != null) { + for (int i=0; i notebooks, boolean readOnly, LinkedNotebook linked) { + logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotebooks"); + if (notebooks != null) { + for (int i=0; i newNotes, String token) { + if (newNotes == null) + return; + for (int i=0; i notes = conn.getNoteTable().getDirtyLinked(notebookGuid); + logger.log(logger.EXTREME, "Number of changes found: " +notes.size()); + for (int i=0; i