/*\r
- * This file is part of NeverNote \r
+ * This file is part of NixNote \r
* Copyright 2009 Randy Baumgarte\r
* \r
* This file may be licensed under the terms of of the\r
import java.util.Calendar;\r
import java.util.Date;\r
import java.util.GregorianCalendar;\r
+import java.util.HashMap;\r
import java.util.List;\r
import java.util.TreeSet;\r
import java.util.Vector;\r
import com.evernote.edam.error.EDAMSystemException;\r
import com.evernote.edam.error.EDAMUserException;\r
import com.evernote.edam.notestore.NoteStore;\r
+import com.evernote.edam.notestore.NoteStore.Client;\r
import com.evernote.edam.notestore.SyncChunk;\r
import com.evernote.edam.notestore.SyncState;\r
import com.evernote.edam.type.Data;\r
import com.trolltech.qt.core.QFile;\r
import com.trolltech.qt.core.QIODevice.OpenModeFlag;\r
import com.trolltech.qt.core.QObject;\r
+import com.trolltech.qt.core.QTextCodec;\r
import com.trolltech.qt.gui.QMessageBox;\r
\r
import cx.fbn.nevernote.signals.NoteIndexSignal;\r
private DatabaseConnection conn;\r
private boolean idle;\r
public boolean error;\r
+ public volatile Vector<String> errorSharedNotebooks;\r
+ public volatile HashMap<String,String> errorSharedNotebooksIgnored;\r
public volatile boolean isConnected;\r
public volatile boolean keepRunning;\r
public volatile String authToken;\r
private long evernoteUpdateCount;\r
+ private final String userAgent = "NixNote/" + System.getProperty("os.name")\r
+ +"/"+System.getProperty("java.vendor") + "/"\r
+ + System.getProperty("java.version") +";";\r
\r
- public volatile NoteStore.Client noteStore;\r
+ public volatile NoteStore.Client localNoteStore;\r
private UserStore.Client userStore;\r
\r
public volatile StatusSignal status;\r
private static int MAX_QUEUED_WAITING = 1000;\r
String dbuid;\r
String dburl;\r
+ String indexUrl;\r
+ String resourceUrl;\r
String dbpswd;\r
String dbcpswd;\r
private final TreeSet<String> ignoreTags;\r
private final TreeSet<String> ignoreNotebooks;\r
private final TreeSet<String> ignoreLinkedNotebooks;\r
+ private HashMap<String,String> badTagSync;\r
\r
\r
\r
- public SyncRunner(String logname, String u, String uid, String pswd, String cpswd) {\r
+ public SyncRunner(String logname, String u, String i, String r, String uid, String pswd, String cpswd) {\r
logger = new ApplicationLogger(logname);\r
\r
noteSignal = new NoteSignal();\r
searchSignal = new SavedSearchSignal();\r
syncSignal = new SyncSignal();\r
resourceSignal = new NoteResourceSignal();\r
+ resourceUrl = r;\r
+ indexUrl = i;\r
dbuid = uid;\r
dburl = u;\r
dbpswd = pswd;\r
authRefreshNeeded = false;\r
keepRunning = true;\r
idle = true;\r
- noteStore = null;\r
- userStore = null;\r
- authToken = null;\r
disableUploads = false;\r
ignoreTags = new TreeSet<String>();\r
ignoreNotebooks = new TreeSet<String>();\r
}\r
@Override\r
public void run() {\r
+ errorSharedNotebooks = new Vector<String>();\r
+ errorSharedNotebooksIgnored = new HashMap<String,String>();\r
try {\r
logger.log(logger.EXTREME, "Starting thread");\r
- conn = new DatabaseConnection(logger, dburl, dbuid, dbpswd, dbcpswd, 200);\r
+ conn = new DatabaseConnection(logger, dburl, indexUrl, resourceUrl, dbuid, dbpswd, dbcpswd, 200);\r
while(keepRunning) {\r
+ logger.log(logger.EXTREME, "Blocking until work is found");\r
String work = workQueue.take();\r
logger.log(logger.EXTREME, "Work found: " +work);\r
- if (work.equalsIgnoreCase("stop"))\r
+ if (work.equalsIgnoreCase("stop")) {\r
+ idle=false;\r
return;\r
+ }\r
idle=false;\r
error=false;\r
if (authRefreshNeeded == true || !isConnected) {\r
updateSequenceNumber = conn.getSyncTable().getUpdateSequenceNumber();\r
try {\r
logger.log(logger.EXTREME, "Beginning sync");\r
- evernoteSync();\r
+ evernoteSync(localNoteStore);\r
logger.log(logger.EXTREME, "Sync finished");\r
} catch (UnknownHostException e) {\r
status.message.emit(e.getMessage());\r
}\r
}\r
- dirtyNoteGuids = null;\r
idle=true;\r
logger.log(logger.EXTREME, "Signaling refresh finished. refreshNeeded=" +refreshNeeded);\r
syncSignal.finished.emit(refreshNeeded);\r
}\r
public void setNoteStore(NoteStore.Client c) {\r
logger.log(logger.EXTREME, "Setting NoteStore in sync thread");\r
- noteStore = c;\r
+ localNoteStore = c;\r
}\r
public void setUserStore(UserStore.Client c) {\r
logger.log(logger.EXTREME, "Setting UserStore in sync thread");\r
//***************************************************************\r
// Synchronize changes with Evernote\r
@SuppressWarnings("unused")\r
- private void evernoteSync() throws java.net.UnknownHostException {\r
+ private void evernoteSync(Client noteStore) throws java.net.UnknownHostException {\r
logger.log(logger.HIGH, "Entering SyncRunner.evernoteSync");\r
\r
// Rebuild list of tags & notebooks to ignore\r
}\r
// Check for "special" sync instructions\r
String syncLinked = conn.getSyncTable().getRecord("FullLinkedNotebookSync");\r
- String syncShared = conn.getSyncTable().getRecord("FullLinkedNotebookSync");\r
+ String syncShared = conn.getSyncTable().getRecord("FullSharedNotebookSync");\r
String syncNotebooks = conn.getSyncTable().getRecord("FullNotebookSync");\r
String syncInkNoteImages = conn.getSyncTable().getRecord("FullInkNoteImageSync");\r
if (syncLinked != null) {\r
- downloadAllLinkedNotebooks();\r
+ downloadAllLinkedNotebooks(localNoteStore);\r
}\r
if (syncShared != null) {\r
- downloadAllSharedNotebooks();\r
+ downloadAllSharedNotebooks(localNoteStore);\r
}\r
if (syncNotebooks != null) {\r
- downloadAllNotebooks();\r
+ downloadAllNotebooks(localNoteStore);\r
}\r
\r
if (syncInkNoteImages != null) {\r
logger.log(logger.EXTREME, "Refresh needed is true");\r
refreshNeeded = true;\r
logger.log(logger.EXTREME, "Downloading changes");\r
- syncRemoteToLocal();\r
+ syncRemoteToLocal(localNoteStore);\r
}\r
\r
//*****************************************\r
logger.log(logger.EXTREME, "Uploading changes");\r
// Synchronize remote changes\r
if (!error)\r
- syncExpunged();\r
+ syncExpunged(localNoteStore);\r
if (!error)\r
- syncLocalTags();\r
+ syncLocalTags(localNoteStore);\r
if (!error)\r
- syncLocalNotebooks();\r
+ syncLocalNotebooks(localNoteStore);\r
if (!error)\r
- syncLocalLinkedNotebooks();\r
+ syncLocalLinkedNotebooks(localNoteStore);\r
if (!error) \r
- syncDeletedNotes();\r
+ syncDeletedNotes(localNoteStore);\r
if (!error)\r
syncLocalNotes();\r
if (!error)\r
- syncLocalSavedSearches();\r
+ syncLocalSavedSearches(localNoteStore);\r
}\r
\r
status.message.emit(tr("Cleaning up"));\r
syncSignal.refreshLists.emit();\r
\r
if (!error) {\r
- logger.log(logger.EXTREME, "Sync completed. Errors=" +error);\r
+ logger.log(logger.LOW, "Sync completed. Errors=" +error);\r
if (!disableUploads) \r
status.message.emit(tr("Synchronizing complete"));\r
else\r
}\r
\r
// Sync deleted items with Evernote\r
- private void syncExpunged() {\r
+ private void syncExpunged(Client noteStore) {\r
logger.log(logger.HIGH, "Entering SyncRunner.syncExpunged");\r
\r
List<DeletedItemRecord> expunged = conn.getDeletedTable().getAllDeleted();\r
boolean error = false;\r
for (int i=0; i<expunged.size() && keepRunning; i++) {\r
- \r
+\r
if (authRefreshNeeded)\r
if (!refreshConnection())\r
return;\r
logger.log(logger.EXTREME, "Tag expunged");\r
updateSequenceNumber = noteStore.expungeTag(authToken, expunged.get(i).guid);\r
conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
- \r
+ conn.getSyncTable().setLastSequenceDate(sequenceDate);\r
+ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
+ conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "TAG"); \r
}\r
if (expunged.get(i).type.equalsIgnoreCase("NOTEBOOK")) {\r
logger.log(logger.EXTREME, "Notebook expunged");\r
updateSequenceNumber = noteStore.expungeNotebook(authToken, expunged.get(i).guid);\r
conn.getSyncTable().setLastSequenceDate(sequenceDate);\r
+ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
+ conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "NOTEBOOK");\r
}\r
if (expunged.get(i).type.equalsIgnoreCase("NOTE")) {\r
logger.log(logger.EXTREME, "Note expunged");\r
updateSequenceNumber = noteStore.deleteNote(authToken, expunged.get(i).guid);\r
+ refreshNeeded = true;\r
+ conn.getSyncTable().setLastSequenceDate(sequenceDate);\r
conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
+ conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "NOTE");\r
}\r
if (expunged.get(i).type.equalsIgnoreCase("SAVEDSEARCH")) {\r
logger.log(logger.EXTREME, "saved search expunged");\r
updateSequenceNumber = noteStore.expungeSearch(authToken, expunged.get(i).guid);\r
conn.getSyncTable().setLastSequenceDate(sequenceDate);\r
+ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
+ conn.getDeletedTable().expungeDeletedItem(expunged.get(i).guid, "SAVEDSEARCH");\r
}\r
} catch (EDAMUserException e) {\r
- logger.log(logger.LOW, "EDAM User Excepton in syncExpunged: " +expunged.get(i).guid);\r
- logger.log(logger.LOW, e.getStackTrace());\r
- error = true;\r
+ logger.log(logger.LOW, "EDAM User Excepton in syncExpunged: " +expunged.get(i).guid); // This can happen if we try to delete a deleted note\r
} catch (EDAMSystemException e) {\r
logger.log(logger.LOW, "EDAM System Excepton in syncExpunged: "+expunged.get(i).guid);\r
logger.log(logger.LOW, e.getStackTrace());\r
error=true;\r
} catch (EDAMNotFoundException e) {\r
logger.log(logger.LOW, "EDAM Not Found Excepton in syncExpunged: "+expunged.get(i).guid);\r
-// logger.log(logger.LOW, e.getStackTrace());\r
- //error=true;\r
} catch (TException e) {\r
logger.log(logger.LOW, "EDAM TExcepton in syncExpunged: "+expunged.get(i).guid);\r
logger.log(logger.LOW, e.getStackTrace());\r
logger.log(logger.HIGH, "Leaving SyncRunner.syncExpunged");\r
\r
}\r
- private void syncDeletedNotes() {\r
+ private void syncDeletedNotes(Client noteStore) {\r
if (syncDeletedContent)\r
return;\r
logger.log(logger.HIGH, "Entering SyncRunner.syncDeletedNotes");\r
List<Note> notes = conn.getNoteTable().getDirty();\r
// Sync the local notebooks with Evernote's\r
for (int i=0; i<notes.size() && keepRunning; i++) {\r
- syncLocalNote(notes.get(i), authToken);\r
+ syncLocalNote(localNoteStore, notes.get(i), authToken);\r
}\r
logger.log(logger.HIGH, "Entering SyncRunner.syncNotes");\r
\r
}\r
// Sync notes with Evernote\r
- private void syncLocalNote(Note enNote, String token) {\r
+ private void syncLocalNote(Client noteStore, Note enNote, String token) {\r
logger.log(logger.HIGH, "Entering SyncRunner.syncNotes");\r
status.message.emit(tr("Sending local notes."));\r
\r
}\r
\r
// Sync Notebooks with Evernote\r
- private void syncLocalNotebooks() {\r
+ private void syncLocalNotebooks(Client noteStore) {\r
logger.log(logger.HIGH, "Entering SyncRunner.syncLocalNotebooks");\r
\r
status.message.emit(tr("Sending local notebooks."));\r
\r
}\r
// Sync Tags with Evernote\r
- private void syncLocalTags() {\r
+ private void syncLocalTags(Client noteStore) {\r
logger.log(logger.HIGH, "Entering SyncRunner.syncLocalTags");\r
List<Tag> remoteList = new ArrayList<Tag>();\r
status.message.emit(tr("Sending local tags."));\r
\r
int sequence;\r
\r
+ if (badTagSync == null)\r
+ badTagSync = new HashMap<String,String>();\r
+ else\r
+ badTagSync.clear();\r
+ \r
Tag enTag = findNextTag();\r
- while(enTag!=null) {\r
+ \r
+ // This is a hack. Sometimes this function goes flookey and goes into a \r
+ // perpetual loop. This causes NeverNote to flood Evernote's servers.\r
+ // This is a safety valve to prevent unlimited loops.\r
+ int maxCount = conn.getTagTable().getDirty().size()+10;\r
+ int loopCount = 0;\r
+ \r
+ while(enTag!=null && loopCount < maxCount) {\r
+ loopCount++;\r
if (authRefreshNeeded)\r
if (!refreshConnection())\r
return;\r
updateSequenceNumber = sequence;\r
conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
} catch (EDAMUserException e) {\r
- logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags");\r
- logger.log(logger.LOW, e.toString()); \r
+ logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags: " +enTag.getName());\r
+ logger.log(logger.LOW, e.toString());\r
+ badTagSync.put(enTag.getGuid(),null);\r
error = true;\r
} catch (EDAMSystemException e) {\r
- logger.log(logger.LOW, "** EDAM System Excepton syncLocalTags");\r
+ logger.log(logger.LOW, "** EDAM System Excepton syncLocalTags: " +enTag.getName());\r
logger.log(logger.LOW, e.toString()); \r
+ badTagSync.put(enTag.getGuid(),null);\r
error = true;\r
} catch (EDAMNotFoundException e) {\r
- logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalTags");\r
- logger.log(logger.LOW, e.toString()); \r
+ logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalTags: " +enTag.getName());\r
+ logger.log(logger.LOW, e.toString());\r
+ badTagSync.put(enTag.getGuid(),null);\r
error = true;\r
} catch (TException e) {\r
- logger.log(logger.LOW, "*** EDAM TExcepton syncLocalTags");\r
- logger.log(logger.LOW, e.toString()); \r
+ logger.log(logger.LOW, "*** EDAM TExcepton syncLocalTags: " +enTag.getName());\r
+ logger.log(logger.LOW, e.toString());\r
+ badTagSync.put(enTag.getGuid(),null);\r
error = true;\r
} \r
\r
}\r
logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalTags");\r
}\r
- private void syncLocalLinkedNotebooks() {\r
+ private void syncLocalLinkedNotebooks(Client noteStore) {\r
logger.log(logger.HIGH, "Entering SyncRunner.syncLocalLinkedNotebooks");\r
\r
List<String> list = conn.getLinkedNotebookTable().getDirtyGuids();\r
logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalLinkedNotebooks");\r
}\r
// Sync Saved Searches with Evernote\r
- private void syncLocalSavedSearches() {\r
+ private void syncLocalSavedSearches(Client noteStore) {\r
logger.log(logger.HIGH, "Entering SyncRunner.syncLocalSavedSearches");\r
List<SavedSearch> remoteList = new ArrayList<SavedSearch>();\r
status.message.emit(tr("Sending saved searches."));\r
error = true;\r
} \r
}\r
+\r
logger.log(logger.HIGH, "Entering SyncRunner.syncLocalSavedSearches");\r
} \r
\r
// Sync evernote changes with local database\r
- private void syncRemoteToLocal() {\r
+ private void syncRemoteToLocal(Client noteStore) {\r
logger.log(logger.HIGH, "Entering SyncRunner.syncRemoteToLocal");\r
\r
List<Note> dirtyNotes = conn.getNoteTable().getDirty();\r
if (!refreshConnection())\r
return;\r
\r
- chunk = null;\r
int sequence = updateSequenceNumber;\r
try {\r
+// conn.beginTransaction();\r
logger.log(logger.EXTREME, "Getting chunk from Evernote");\r
chunk = noteStore.getSyncChunk(authToken, sequence, chunkSize, fullSync);\r
} catch (EDAMUserException e) {\r
syncRemoteTags(chunk.getTags());\r
syncRemoteSavedSearches(chunk.getSearches());\r
syncRemoteNotebooks(chunk.getNotebooks());\r
- syncRemoteNotes(chunk.getNotes(), fullSync, authToken);\r
- syncRemoteResources(chunk.getResources());\r
+ syncRemoteNotes(noteStore, chunk.getNotes(), fullSync, authToken);\r
+ syncRemoteResources(noteStore, chunk.getResources());\r
syncRemoteLinkedNotebooks(chunk.getLinkedNotebooks());\r
+ \r
+ // Signal about any updated notes to invalidate the cache\r
+ for (int i=0; i<chunk.getNotesSize(); i++) \r
+ noteSignal.noteChanged.emit(chunk.getNotes().get(i).getGuid(), null); \r
syncExpungedNotes(chunk);\r
\r
\r
\r
\r
// Save the chunk sequence number\r
- if (!error && chunk.getChunkHighUSN() > 0) {\r
+ if (!error && chunk.getChunkHighUSN() > 0 && keepRunning) {\r
logger.log(logger.EXTREME, "emitting sequence number to main thread");\r
updateSequenceNumber = chunk.getChunkHighUSN();\r
conn.getSyncTable().setLastSequenceDate(chunk.getCurrentTime());\r
conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
+// conn.commitTransaction();\r
}\r
\r
\r
pct = pct/evernoteUpdateCount;\r
status.message.emit(tr("Downloading ") +new Long(pct).toString()+tr("% complete."));\r
}\r
+// conn.commitTransaction();\r
}\r
-\r
logger.log(logger.HIGH, "Leaving SyncRunner.syncRemoteToLocal");\r
}\r
// Sync expunged notes\r
// List<SharedNotebook> books = noteStore.getSharedNotebookByAuth(authToken);\r
// }\r
// Sync remote Resources\r
- private void syncRemoteResources(List<Resource> resource) {\r
+ private void syncRemoteResources(Client noteStore, List<Resource> resource) {\r
logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteResources");\r
if (resource != null) {\r
for (int i=0; i<resource.size() && keepRunning; i++) {\r
- syncRemoteResource(resource.get(i), authToken);\r
+ syncRemoteResource(noteStore, resource.get(i), authToken);\r
}\r
}\r
logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteResources");\r
}\r
// Sync remote resource\r
- private void syncRemoteResource(Resource resource, String authToken) {\r
+ private void syncRemoteResource(Client noteStore, Resource resource, String authToken) {\r
// This is how the logic for this works.\r
// 1.) If the resource is not in the local database, we add it.\r
// 2.) If a copy of the resource is in the local database and the note isn't dirty, we update the local copy\r
// is a conflict. The note conflict should get a copy of the resource at that time.\r
\r
boolean saveNeeded = false;\r
- /* #1 */ Resource r = getEvernoteResource(resource.getGuid(), true,true,true, authToken);\r
+ /* #1 */ Resource r = getEvernoteResource(noteStore, resource.getGuid(), true,true,true, authToken);\r
Resource l = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), false);\r
if (l == null) {\r
saveNeeded = true;\r
\r
}\r
// Sync remote notes\r
- private void syncRemoteNotes(List<Note> note, boolean fullSync, String token) {\r
+ private void syncRemoteNotes(Client noteStore, List<Note> note, boolean fullSync, String token) {\r
logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotes");\r
if (note != null) {\r
for (int i=0; i<note.size() && keepRunning; i++) {\r
- Note n = getEvernoteNote(note.get(i).getGuid(), true, fullSync, true,true, token);\r
+ Note n = getEvernoteNote(noteStore, note.get(i).getGuid(), true, fullSync, true,true, token);\r
syncRemoteNote(n, fullSync, token);\r
}\r
}\r
if ((conflictingNote || fullSync) && !ignoreNote) {\r
logger.log(logger.EXTREME, "Saving Note");\r
conn.getNoteTable().syncNote(n, false);\r
- noteSignal.noteChanged.emit(n.getGuid(), null); // Signal to ivalidate note cache\r
+ // The following was commented out because it caused a race condition on the database where resources \r
+ // may be lost. We do the same thing elsewhere;.\r
+// noteSignal.noteChanged.emit(n.getGuid(), null); // Signal to ivalidate note cache \r
noteSignal.noteDownloaded.emit(n, true); // Signal to add note to index\r
logger.log(logger.EXTREME, "Note Saved");\r
if (fullSync && n.getResources() != null) {\r
}\r
}\r
}\r
- private Note getEvernoteNote(String guid, boolean withContent, boolean withResourceData, boolean withResourceRecognition, boolean withResourceAlternateData, String token) { \r
+ private Note getEvernoteNote(Client noteStore, String guid, boolean withContent, boolean withResourceData, boolean withResourceRecognition, boolean withResourceAlternateData, String token) { \r
Note n = null;\r
try {\r
logger.log(logger.EXTREME, "Retrieving note " +guid);\r
}\r
return n;\r
}\r
- private Resource getEvernoteResource(String guid, boolean withData, boolean withRecognition, boolean withAttributes, String token) { \r
+ private Resource getEvernoteResource(Client noteStore, String guid, boolean withData, boolean withRecognition, boolean withAttributes, String token) { \r
Resource n = null;\r
try {\r
logger.log(logger.EXTREME, "Retrieving resource " +guid);\r
// Find the parent. If the parent has a sequence > 0 then it is a good\r
// parent.\r
for (int i=0; i<tags.size() && keepRunning; i++) {\r
- if (tags.get(i).getParentGuid() == null) {\r
- logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - tag found without parent");\r
- return tags.get(i);\r
- }\r
- Tag parentTag = conn.getTagTable().getTag(tags.get(i).getParentGuid());\r
- if (parentTag.getUpdateSequenceNum() > 0) {\r
- logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - tag found");\r
- return tags.get(i);\r
+ if (!badTagSync.containsKey(tags.get(i).getGuid())) {\r
+ if (tags.get(i).getParentGuid() == null) {\r
+ logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - tag found without parent");\r
+ return tags.get(i);\r
+ }\r
+ Tag parentTag = conn.getTagTable().getTag(tags.get(i).getParentGuid());\r
+ if (parentTag.getUpdateSequenceNum() > 0) {\r
+ logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - tag found");\r
+ return tags.get(i);\r
+ }\r
}\r
}\r
\r
public boolean enConnect() {\r
try {\r
userStoreTrans = new THttpClient(userStoreUrl);\r
+ userStoreTrans.setCustomHeader("User-Agent", userAgent);\r
} catch (TTransportException e) {\r
QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage());\r
mb.exec();\r
\r
boolean versionOk = false;\r
try {\r
- versionOk = userStore.checkVersion("NeverNote", \r
+ versionOk = userStore.checkVersion("NixNote", \r
com.evernote.edam.userstore.Constants.EDAM_VERSION_MAJOR, \r
com.evernote.edam.userstore.Constants.EDAM_VERSION_MINOR);\r
} catch (TException e) {\r
authToken = authResult.getAuthenticationToken(); \r
noteStoreUrl = noteStoreUrlBase + user.getShardId();\r
syncSignal.saveAuthToken.emit(authToken);\r
- syncSignal.saveNoteStore.emit(noteStore);\r
+ syncSignal.saveNoteStore.emit(localNoteStore);\r
\r
\r
try {\r
noteStoreTrans = new THttpClient(noteStoreUrl);\r
+ noteStoreTrans.setCustomHeader("User-Agent", userAgent);\r
} catch (TTransportException e) {\r
QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage());\r
mb.exec();\r
isConnected = false;\r
} \r
noteStoreProt = new TBinaryProtocol(noteStoreTrans);\r
- noteStore = \r
+ localNoteStore = \r
new NoteStore.Client(noteStoreProt, noteStoreProt); \r
isConnected = true;\r
authTimeRemaining = authResult.getExpiration() - authResult.getCurrentTime();\r
}\r
\r
private Note getNoteContent(Note n) {\r
- n.setContent(conn.getNoteTable().getNoteContentBinary(n.getGuid()));\r
+ QTextCodec codec = QTextCodec.codecForLocale();\r
+ codec = QTextCodec.codecForName("UTF-8");\r
+ n.setContent(codec.toUnicode(new QByteArray(n.getContent())));\r
return n;\r
}\r
\r
//*********************************************************\r
//* Special download instructions. Used for DB upgrades\r
//*********************************************************\r
- private void downloadAllSharedNotebooks() {\r
+ private void downloadAllSharedNotebooks(Client noteStore) {\r
try {\r
List<SharedNotebook> books = noteStore.listSharedNotebooks(authToken);\r
logger.log(logger.LOW, "Shared notebooks found = " +books.size());\r
logger.log(logger.LOW, e1.getMessage());\r
}\r
}\r
- private void downloadAllNotebooks() {\r
+ private void downloadAllNotebooks(Client noteStore) {\r
try {\r
List<Notebook> books = noteStore.listNotebooks(authToken);\r
logger.log(logger.LOW, "Shared notebooks found = " +books.size());\r
return;\r
}\r
}\r
- private void downloadAllLinkedNotebooks() {\r
+ private void downloadAllLinkedNotebooks(Client noteStore) {\r
try {\r
List<LinkedNotebook> books = noteStore.listLinkedNotebooks(authToken);\r
logger.log(logger.LOW, "Linked notebooks found = " +books.size());\r
try {\r
post.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));\r
} catch (UnsupportedEncodingException e1) {\r
- // TODO Auto-generated catch block\r
e1.printStackTrace();\r
}\r
try {\r
logger.log(logger.MEDIUM, "Authenticating Shared Notebooks");\r
status.message.emit(tr("Synchronizing shared notebooks."));\r
List<LinkedNotebook> books = conn.getLinkedNotebookTable().getAll();\r
-\r
+ \r
+ errorSharedNotebooks.clear();\r
+ \r
for (int i=0; i<books.size(); i++) {\r
+ if (errorSharedNotebooksIgnored.containsKey(books.get(i).getGuid()))\r
+ break;\r
try {\r
long lastSyncDate = conn.getLinkedNotebookTable().getLastSequenceDate(books.get(i).getGuid());\r
int lastSequenceNumber = conn.getLinkedNotebookTable().getLastSequenceNumber(books.get(i).getGuid());\r
- linkedAuthResult = noteStore.authenticateToSharedNotebook(books.get(i).getShareKey(), authToken);\r
+\r
+ logger.log(logger.EXTREME, "Last Sequence Number on file: " +lastSequenceNumber);\r
+ \r
+ // Authenticate to the owner's shard\r
+ String linkedNoteStoreUrl = noteStoreUrlBase + books.get(i).getShardId();\r
+ logger.log(logger.EXTREME, "linkedNoteStoreURL: " +linkedNoteStoreUrl);\r
+ THttpClient linkedNoteStoreTrans = new THttpClient(linkedNoteStoreUrl);\r
+ TBinaryProtocol linkedNoteStoreProt = new TBinaryProtocol(linkedNoteStoreTrans);\r
+ Client linkedNoteStore = new NoteStore.Client(linkedNoteStoreProt, linkedNoteStoreProt); \r
+\r
+ linkedAuthResult = null;\r
+ if (books.get(i).getShareKey() != null) {\r
+ logger.log(logger.EXTREME, "Share Key Not Null: " +books.get(i).getShareKey());\r
+ linkedAuthResult = linkedNoteStore.authenticateToSharedNotebook(books.get(i).getShareKey(), authToken);\r
+ logger.log(logger.EXTREME, "Authentication Token" +linkedAuthResult.getAuthenticationToken());\r
+ } else {\r
+ logger.log(logger.EXTREME, "Share key is null ");\r
+ linkedAuthResult = new AuthenticationResult();\r
+ linkedAuthResult.setAuthenticationToken("");\r
+ }\r
SyncState linkedSyncState = \r
- noteStore.getLinkedNotebookSyncState(linkedAuthResult.getAuthenticationToken(), books.get(i));\r
+ linkedNoteStore.getLinkedNotebookSyncState(linkedAuthResult.getAuthenticationToken(), books.get(i));\r
if (linkedSyncState.getUpdateCount() > lastSequenceNumber) {\r
if (lastSyncDate < linkedSyncState.getFullSyncBefore()) {\r
lastSequenceNumber = 0;\r
} \r
- syncLinkedNotebook(books.get(i), lastSequenceNumber, linkedSyncState.getUpdateCount());\r
+ syncLinkedNotebook(linkedNoteStore, books.get(i), \r
+ //lastSequenceNumber, linkedSyncState.getUpdateCount(), linkedAuthResult.getAuthenticationToken());\r
+ lastSequenceNumber, linkedSyncState.getUpdateCount(), authToken);\r
}\r
\r
// Synchronize local changes\r
- syncLocalLinkedNoteChanges(books.get(i));\r
+ syncLocalLinkedNoteChanges(linkedNoteStore, books.get(i));\r
\r
} catch (EDAMUserException e) {\r
- // TODO Auto-generated catch block\r
e.printStackTrace();\r
} catch (EDAMNotFoundException e) {\r
status.message.emit(tr("Error synchronizing \" " +\r
books.get(i).getShareName()+"\". Please verify you still have access to that shared notebook."));\r
+ errorSharedNotebooks.add(books.get(i).getGuid());\r
+ errorSharedNotebooksIgnored.put(books.get(i).getGuid(), books.get(i).getGuid());\r
+ logger.log(logger.LOW, "Error synchronizing shared notebook. EDAMNotFound: "+e.getMessage());\r
+ logger.log(logger.LOW, e.getStackTrace());\r
error = true;\r
e.printStackTrace();\r
} catch (EDAMSystemException e) {\r
- // TODO Auto-generated catch block\r
+ error = true;\r
+ logger.log(logger.LOW, "System error authenticating against shared notebook. "+\r
+ "Key: "+books.get(i).getShareKey() +" Error:" +e.getMessage());\r
e.printStackTrace();\r
} catch (TException e) {\r
- // TODO Auto-generated catch block\r
+ error = true;\r
e.printStackTrace();\r
}\r
}\r
conn.getTagTable().removeUnusedLinkedTags();\r
conn.getTagTable().cleanupTags();\r
tagSignal.listChanged.emit();\r
+ return;\r
}\r
\r
\r
//**************************************************************\r
//* Linked notebook contents (from someone else's account)\r
//*************************************************************\r
- private void syncLinkedNotebook(LinkedNotebook book, int usn, int highSequence) {\r
- \r
+ private void syncLinkedNotebook(Client linkedNoteStore, LinkedNotebook book, int usn, int highSequence, String token) {\r
+ logger.log(logger.EXTREME, "Entering syncLinkedNotebook");\r
+ if (ignoreLinkedNotebooks.contains(book.getGuid()))\r
+ return;\r
List<Note> dirtyNotes = conn.getNoteTable().getDirtyLinkedNotes();\r
if (dirtyNoteGuids == null) \r
dirtyNoteGuids = new Vector<String>();\r
boolean fullSync = false;\r
if (usn == 0)\r
fullSync = true;\r
- while (usn < highSequence) {\r
+ boolean syncError = false;\r
+ while (usn < highSequence && !syncError) {\r
+ refreshNeeded = true;\r
try {\r
SyncChunk chunk = \r
- noteStore.getLinkedNotebookSyncChunk(authToken, book, usn, 10, fullSync);\r
+ linkedNoteStore.getLinkedNotebookSyncChunk(token, book, usn, 10, fullSync);\r
+ \r
+ // Expunge notes\r
+ syncExpungedNotes(chunk);\r
\r
- if (!ignoreLinkedNotebooks.contains(book.getGuid()))\r
- syncRemoteNotes(chunk.getNotes(), fullSync, linkedAuthResult.getAuthenticationToken());\r
- findNewLinkedTags(chunk.getNotes(), linkedAuthResult.getAuthenticationToken());\r
+ logger.log(logger.EXTREME, "Syncing remote notes: " +chunk.getNotesSize());\r
+ syncRemoteNotes(linkedNoteStore, chunk.getNotes(), fullSync, linkedAuthResult.getAuthenticationToken());\r
+ logger.log(logger.EXTREME, "Finding new linked tags");\r
+ findNewLinkedTags(linkedNoteStore, chunk.getNotes(), linkedAuthResult.getAuthenticationToken());\r
+ // Sync resources\r
+ logger.log(logger.EXTREME, "Synchronizing tags: " +chunk.getTagsSize());\r
for (int i=0; i<chunk.getResourcesSize(); i++) {\r
- syncRemoteResource(chunk.getResources().get(i), linkedAuthResult.getAuthenticationToken());\r
+ syncRemoteResource(linkedNoteStore, chunk.getResources().get(i), linkedAuthResult.getAuthenticationToken());\r
}\r
- syncRemoteLinkedNotebooks(chunk.getNotebooks(), false, book);\r
- SharedNotebook s = noteStore.getSharedNotebookByAuth(linkedAuthResult.getAuthenticationToken());\r
- syncLinkedTags(chunk.getTags(), s.getNotebookGuid());\r
+ logger.log(logger.EXTREME, "Synchronizing linked notebooks: " +chunk.getNotebooksSize());\r
+ syncRemoteLinkedNotebooks(linkedNoteStore, chunk.getNotebooks(), false, book);\r
+ syncLinkedTags(chunk.getTags(), book.getGuid());\r
\r
- \r
- // Expunge records\r
+ // Go through & signal any notes that have changed so we can refresh the user's view\r
+ for (int i=0; i<chunk.getNotesSize(); i++) \r
+ noteSignal.noteChanged.emit(chunk.getNotes().get(i).getGuid(), null);\r
+\r
+ // Expunge Notebook records\r
+ logger.log(logger.EXTREME, "Expunging linked notebooks: " +chunk.getExpungedLinkedNotebooksSize());\r
for (int i=0; i<chunk.getExpungedLinkedNotebooksSize(); i++) {\r
conn.getLinkedNotebookTable().expungeNotebook(chunk.getExpungedLinkedNotebooks().get(i), false);\r
}\r
conn.getLinkedNotebookTable().setLastSequenceDate(book.getGuid(),chunk.getCurrentTime());\r
conn.getLinkedNotebookTable().setLastSequenceNumber(book.getGuid(),chunk.getChunkHighUSN());\r
} catch (EDAMUserException e) {\r
- // TODO Auto-generated catch block\r
+ syncError = true;\r
+ status.message.emit(tr("EDAM UserException synchronizing linked notbook. See the log for datails."));\r
e.printStackTrace();\r
+ logger.log(logger.LOW, tr("EDAM UserException synchronizing linked notbook ")+ e.getMessage());\r
} catch (EDAMSystemException e) {\r
- // TODO Auto-generated catch block\r
+ syncError = true;\r
+ status.message.emit(tr("EDAM SystemException synchronizing linked notbook. See the log for datails."));\r
e.printStackTrace();\r
+ logger.log(logger.LOW, tr("EDAM SystemException synchronizing linked notbook. See the log for datails") +e.getMessage());\r
} catch (EDAMNotFoundException e) {\r
- // TODO Auto-generated catch block\r
- e.printStackTrace();\r
+ syncError = true;\r
+ status.message.emit(tr("Notebook URL not found. Removing notobook ") +book.getShareName());\r
+ conn.getNotebookTable().deleteLinkedTags(book.getGuid());\r
+ conn.getLinkedNotebookTable().expungeNotebook(book.getGuid(), false);\r
+ logger.log(logger.LOW, tr("Notebook URL not found. Removing notobook ") +e.getMessage());\r
} catch (TException e) {\r
- // TODO Auto-generated catch block\r
+ syncError = true;\r
+ status.message.emit(tr("EDAM TException synchronizing linked notbook. See the log for datails."));\r
e.printStackTrace();\r
+ logger.log(logger.LOW, tr("EDAM TException synchronizing linked notbook. See the log for datails." )+e.getMessage());\r
}\r
}\r
+ logger.log(logger.EXTREME, "leaving syncLinkedNotebook");\r
}\r
// Sync remote tags\r
private void syncLinkedTags(List<Tag> tags, String notebookGuid) {\r
}\r
\r
// Sync notebooks from a linked notebook\r
- private void syncRemoteLinkedNotebooks(List<Notebook> notebooks, boolean readOnly, LinkedNotebook linked) {\r
+ private void syncRemoteLinkedNotebooks(Client noteStore, List<Notebook> notebooks, boolean readOnly, LinkedNotebook linked) {\r
logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotebooks");\r
if (notebooks != null) {\r
for (int i=0; i<notebooks.size() && keepRunning; i++) {\r
try {\r
- SharedNotebook s = noteStore.getSharedNotebookByAuth(linkedAuthResult.getAuthenticationToken());\r
- conn.getLinkedNotebookTable().setNotebookGuid(s.getShareKey(), s.getNotebookGuid());\r
- readOnly = !s.isNotebookModifiable();\r
+ if (!linkedAuthResult.getAuthenticationToken().equals("")) {\r
+ SharedNotebook s = noteStore.getSharedNotebookByAuth(linkedAuthResult.getAuthenticationToken());\r
+ conn.getLinkedNotebookTable().setNotebookGuid(s.getShareKey(), s.getNotebookGuid());\r
+ readOnly = !s.isNotebookModifiable();\r
+ } else {\r
+ readOnly = true;\r
+ }\r
notebooks.get(i).setName(linked.getShareName());\r
notebooks.get(i).setDefaultNotebook(false);\r
conn.getNotebookTable().syncLinkedNotebook(notebooks.get(i), false, readOnly); \r
logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteNotebooks");\r
}\r
\r
- private void findNewLinkedTags(List<Note> newNotes, String token) {\r
+ private void findNewLinkedTags(Client noteStore, List<Note> newNotes, String token) {\r
if (newNotes == null)\r
return;\r
for (int i=0; i<newNotes.size(); i++) {\r
newTag = noteStore.getTag(token, tag);\r
conn.getTagTable().addTag(newTag, false);\r
} catch (EDAMUserException e) {\r
- // TODO Auto-generated catch block\r
e.printStackTrace();\r
} catch (EDAMSystemException e) {\r
- // TODO Auto-generated catch block\r
e.printStackTrace();\r
} catch (EDAMNotFoundException e) {\r
- // TODO Auto-generated catch block\r
e.printStackTrace();\r
} catch (TException e) {\r
- // TODO Auto-generated catch block\r
e.printStackTrace();\r
}\r
\r
}\r
\r
// Synchronize changes locally done to linked notes\r
- private void syncLocalLinkedNoteChanges(LinkedNotebook book) {\r
+ private void syncLocalLinkedNoteChanges(Client noteStore, LinkedNotebook book) {\r
String notebookGuid = conn.getLinkedNotebookTable().getNotebookGuid(book.getGuid());\r
List<Note> notes = conn.getNoteTable().getDirtyLinked(notebookGuid);\r
for (int i=0; i<notes.size(); i++) {\r
- syncLocalNote(notes.get(i), linkedAuthResult.getAuthenticationToken());\r
+ syncLocalNote(noteStore, notes.get(i), linkedAuthResult.getAuthenticationToken());\r
}\r
}\r
\r