*/\r
package cx.fbn.nevernote.threads;\r
\r
+import java.io.BufferedOutputStream;\r
+import java.io.File;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.UnsupportedEncodingException;\r
import java.net.UnknownHostException;\r
import java.util.ArrayList;\r
import java.util.Calendar;\r
import java.util.Date;\r
import java.util.GregorianCalendar;\r
import java.util.List;\r
+import java.util.TreeSet;\r
import java.util.Vector;\r
import java.util.concurrent.LinkedBlockingQueue;\r
\r
+import org.apache.http.HttpEntity;\r
+import org.apache.http.HttpResponse;\r
+import org.apache.http.NameValuePair;\r
+import org.apache.http.client.ClientProtocolException;\r
+import org.apache.http.client.HttpClient;\r
+import org.apache.http.client.entity.UrlEncodedFormEntity;\r
+import org.apache.http.client.methods.HttpPost;\r
+import org.apache.http.impl.client.DefaultHttpClient;\r
+import org.apache.http.message.BasicNameValuePair;\r
+import org.apache.http.protocol.HTTP;\r
import org.apache.thrift.TException;\r
import org.apache.thrift.protocol.TBinaryProtocol;\r
import org.apache.thrift.transport.THttpClient;\r
import com.evernote.edam.notestore.SyncChunk;\r
import com.evernote.edam.notestore.SyncState;\r
import com.evernote.edam.type.Data;\r
+import com.evernote.edam.type.LinkedNotebook;\r
import com.evernote.edam.type.Note;\r
import com.evernote.edam.type.Notebook;\r
import com.evernote.edam.type.Resource;\r
import com.evernote.edam.type.SavedSearch;\r
+import com.evernote.edam.type.SharedNotebook;\r
import com.evernote.edam.type.Tag;\r
import com.evernote.edam.type.User;\r
import com.evernote.edam.userstore.AuthenticationResult;\r
import com.evernote.edam.userstore.UserStore;\r
+import com.trolltech.qt.core.QByteArray;\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.gui.QMessageBox;\r
\r
private final ApplicationLogger logger;\r
private DatabaseConnection conn;\r
private boolean idle;\r
- private boolean error;\r
+ public boolean error;\r
public volatile boolean isConnected;\r
public volatile boolean keepRunning;\r
public volatile String authToken;\r
private THttpClient userStoreTrans;\r
private TBinaryProtocol userStoreProt;\r
private AuthenticationResult authResult;\r
+ private AuthenticationResult linkedAuthResult;\r
private User user; \r
private long authTimeRemaining;\r
public long authRefreshTime;\r
public int updateSequenceNumber;\r
private boolean refreshNeeded;\r
private volatile LinkedBlockingQueue<String> workQueue;\r
-// private static int MAX_EMPTY_QUEUE_COUNT = 1;\r
private static int MAX_QUEUED_WAITING = 1000;\r
String dbuid;\r
String dburl;\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
\r
\r
\r
userStore = null;\r
authToken = null;\r
disableUploads = false;\r
+ ignoreTags = new TreeSet<String>();\r
+ ignoreNotebooks = new TreeSet<String>();\r
+ ignoreLinkedNotebooks = new TreeSet<String>();\r
+ \r
// setAutoDelete(false);\r
workQueue=new LinkedBlockingQueue<String>(MAX_QUEUED_WAITING);\r
}\r
public void run() {\r
try {\r
logger.log(logger.EXTREME, "Starting thread");\r
- conn = new DatabaseConnection(logger, dburl, dbuid, dbpswd, dbcpswd);\r
+ conn = new DatabaseConnection(logger, dburl, dbuid, dbpswd, dbcpswd, 200);\r
while(keepRunning) {\r
String work = workQueue.take();\r
logger.log(logger.EXTREME, "Work found: " +work);\r
return;\r
idle=false;\r
error=false;\r
- if (authRefreshNeeded == true) {\r
+ if (authRefreshNeeded == true || !isConnected) {\r
logger.log(logger.EXTREME, "Refreshing connection");\r
refreshConnection();\r
}\r
idle=true;\r
logger.log(logger.EXTREME, "Signaling refresh finished. refreshNeeded=" +refreshNeeded);\r
syncSignal.finished.emit(refreshNeeded);\r
+ if (error) {\r
+ syncSignal.errorDisconnect.emit();\r
+ status.message.emit(tr("Error synchronizing - see log for details."));\r
+ }\r
}\r
} \r
catch (InterruptedException e1) {\r
@SuppressWarnings("unused")\r
private void evernoteSync() throws java.net.UnknownHostException {\r
logger.log(logger.HIGH, "Entering SyncRunner.evernoteSync");\r
+ \r
+ // Rebuild list of tags & notebooks to ignore\r
+ ignoreNotebooks.clear();\r
+ List<String> ignore = conn.getSyncTable().getIgnoreRecords("NOTEBOOK");\r
+ for (int i=0; i<ignore.size(); i++) \r
+ ignoreNotebooks.add(ignore.get(i));\r
+ \r
+ ignore.clear();\r
+ ignore = conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK");\r
+ for (int i=0; i<ignore.size(); i++) \r
+ ignoreLinkedNotebooks.add(ignore.get(i));\r
+ \r
+ ignoreTags.clear();\r
+ ignore = conn.getSyncTable().getIgnoreRecords("TAG");\r
+ for (int i=0; i<ignore.size(); i++) \r
+ ignoreTags.add(ignore.get(i));\r
\r
+ // Make sure we are connected & should keep running\r
if (isConnected && keepRunning) {\r
error = false;\r
logger.log(logger.EXTREME, "Synchronizing with Evernote");\r
e1.printStackTrace();\r
status.message.emit(tr("User exception getting user account information. Aborting sync and disconnecting"));\r
syncSignal.errorDisconnect.emit();\r
+ error = true;\r
enDisconnect();\r
return;\r
} catch (EDAMSystemException e1) {\r
e1.printStackTrace();\r
status.message.emit(tr("System error user account information. Aborting sync and disconnecting!"));\r
syncSignal.errorDisconnect.emit();\r
+ error = true;\r
enDisconnect();\r
return;\r
} catch (TException e1) {\r
e1.printStackTrace();\r
syncSignal.errorDisconnect.emit();\r
+ error = true;\r
status.message.emit(tr("Transaction error getting user account information. Aborting sync and disconnecting!"));\r
enDisconnect();\r
return;\r
updateSequenceNumber = 0;\r
conn.getSyncTable().setUpdateSequenceNumber(0);\r
}\r
-\r
+ // Check for "special" sync instructions\r
+ String syncLinked = conn.getSyncTable().getRecord("FullLinkedNotebookSync");\r
+ String syncShared = conn.getSyncTable().getRecord("FullLinkedNotebookSync");\r
+ String syncNotebooks = conn.getSyncTable().getRecord("FullNotebookSync");\r
+ String syncInkNoteImages = conn.getSyncTable().getRecord("FullInkNoteImageSync");\r
+ if (syncLinked != null) {\r
+ downloadAllLinkedNotebooks();\r
+ }\r
+ if (syncShared != null) {\r
+ downloadAllSharedNotebooks();\r
+ }\r
+ if (syncNotebooks != null) {\r
+ downloadAllNotebooks();\r
+ }\r
+ \r
+ if (syncInkNoteImages != null) {\r
+ List<String> guids = conn.getNoteTable().noteResourceTable.findInkNotes();\r
+ for (int i=0; i<guids.size(); i++) {\r
+ downloadInkNoteImage(guids.get(i), authToken);\r
+ }\r
+ conn.getSyncTable().deleteRecord("FullInkNoteImageSync");\r
+ }\r
+ \r
// If there are remote changes\r
logger.log(logger.LOW, "Update Count: " +syncState.getUpdateCount());\r
logger.log(logger.LOW, "Last Update Count: " +updateSequenceNumber);\r
syncRemoteToLocal();\r
}\r
\r
+ //*****************************************\r
+ //* Sync linked/shared notebooks \r
+ //*****************************************\r
+ syncLinkedNotebooks();\r
+ \r
if (!disableUploads) {\r
logger.log(logger.EXTREME, "Uploading changes");\r
// Synchronize remote changes\r
syncLocalTags();\r
if (!error)\r
syncLocalNotebooks();\r
+ if (!error)\r
+ syncLocalLinkedNotebooks();\r
if (!error) \r
syncDeletedNotes();\r
if (!error)\r
if (!error)\r
syncLocalSavedSearches();\r
}\r
+ \r
+ status.message.emit(tr("Cleaning up"));\r
+ List<String> notes = conn.getNoteTable().expungeIgnoreSynchronizedNotes(conn.getSyncTable().getIgnoreRecords("NOTEBOOK"), \r
+ conn.getSyncTable().getIgnoreRecords("TAG"), conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK"));\r
+ if (notes.size() > 0)\r
+ syncSignal.refreshLists.emit();\r
+ \r
+ //*****************************************\r
+ //* End of synchronization\r
+ //*****************************************\r
if (refreshNeeded)\r
syncSignal.refreshLists.emit();\r
+ \r
if (!error) {\r
logger.log(logger.EXTREME, "Sync completed. Errors=" +error);\r
- if (!disableUploads)\r
+ if (!disableUploads) \r
status.message.emit(tr("Synchronizing complete"));\r
else\r
status.message.emit(tr("Download syncronization complete. Uploads have been disabled."));\r
}\r
logger.log(logger.HIGH, "Leaving SyncRunner.evernoteSync");\r
}\r
+ \r
// Sync deleted items with Evernote\r
private void syncExpunged() {\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(); i++) {\r
+ for (int i=0; i<expunged.size() && keepRunning; i++) {\r
\r
if (authRefreshNeeded)\r
- refreshConnection();\r
+ if (!refreshConnection())\r
+ return;\r
\r
try {\r
if (expunged.get(i).type.equalsIgnoreCase("TAG")) {\r
for (int i=0; i<notes.size() && keepRunning; i++) {\r
\r
if (authRefreshNeeded)\r
- refreshConnection();\r
+ if (!refreshConnection())\r
+ return;\r
\r
Note enNote = notes.get(i);\r
try {\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
+ }\r
+ logger.log(logger.HIGH, "Entering SyncRunner.syncNotes");\r
+\r
+ }\r
+ // Sync notes with Evernote\r
+ private void syncLocalNote(Note enNote, String token) {\r
+ logger.log(logger.HIGH, "Entering SyncRunner.syncNotes");\r
+ status.message.emit(tr("Sending local notes."));\r
+\r
+ if (authRefreshNeeded)\r
+ if (!refreshConnection())\r
+ return;\r
\r
- if (authRefreshNeeded)\r
- refreshConnection();\r
- \r
- Note enNote = notes.get(i);\r
- if (enNote.isActive()) {\r
- try {\r
- logger.log(logger.EXTREME, "Active dirty note found - non new");\r
- if (enNote.getUpdateSequenceNum() > 0) {\r
- enNote = getNoteContent(enNote);\r
- logger.log(logger.MEDIUM, "Updating note : "+ enNote.getGuid() +" <title>" +enNote.getTitle()+"</title>");\r
- enNote = noteStore.updateNote(authToken, enNote);\r
- } else { \r
- logger.log(logger.EXTREME, "Active dirty found - new note");\r
- logger.log(logger.MEDIUM, "Creating note : "+ enNote.getGuid() +" <title>" +enNote.getTitle()+"</title>");\r
- String oldGuid = enNote.getGuid();\r
- enNote = getNoteContent(enNote);\r
- enNote = noteStore.createNote(authToken, enNote);\r
- noteSignal.guidChanged.emit(oldGuid, enNote.getGuid());\r
- conn.getNoteTable().updateNoteGuid(oldGuid, enNote.getGuid());\r
- }\r
- updateSequenceNumber = enNote.getUpdateSequenceNum();\r
- logger.log(logger.EXTREME, "Saving note");\r
- conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum());\r
- List<Resource> rl = enNote.getResources();\r
- logger.log(logger.EXTREME, "Getting note resources");\r
- for (int j=0; j<enNote.getResourcesSize() && keepRunning; j++) {\r
- Resource newRes = rl.get(j);\r
- Data d = newRes.getData();\r
- if (d!=null) { \r
- logger.log(logger.EXTREME, "Calculating resource hash");\r
- String hash = byteArrayToHexString(d.getBodyHash());\r
- logger.log(logger.EXTREME, "updating resources by hash");\r
- String oldGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(enNote.getGuid(), hash);\r
- conn.getNoteTable().updateNoteResourceGuidbyHash(enNote.getGuid(), newRes.getGuid(), hash);\r
- resourceSignal.resourceGuidChanged.emit(enNote.getGuid(), oldGuid, newRes.getGuid());\r
- }\r
+ if (enNote.isActive()) {\r
+ try {\r
+ logger.log(logger.EXTREME, "Active dirty note found - non new");\r
+ if (enNote.getUpdateSequenceNum() > 0) {\r
+ enNote = getNoteContent(enNote);\r
+ logger.log(logger.MEDIUM, "Updating note : "+ enNote.getGuid() +" <title>" +enNote.getTitle()+"</title>");\r
+ enNote = noteStore.updateNote(token, enNote);\r
+ } else { \r
+ logger.log(logger.EXTREME, "Active dirty found - new note");\r
+ logger.log(logger.MEDIUM, "Creating note : "+ enNote.getGuid() +" <title>" +enNote.getTitle()+"</title>");\r
+ String oldGuid = enNote.getGuid();\r
+ enNote = getNoteContent(enNote);\r
+ enNote = noteStore.createNote(token, enNote);\r
+ noteSignal.guidChanged.emit(oldGuid, enNote.getGuid());\r
+ conn.getNoteTable().updateNoteGuid(oldGuid, enNote.getGuid());\r
+ }\r
+ updateSequenceNumber = enNote.getUpdateSequenceNum();\r
+ logger.log(logger.EXTREME, "Saving note");\r
+ conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum());\r
+ List<Resource> rl = enNote.getResources();\r
+ logger.log(logger.EXTREME, "Getting note resources");\r
+ for (int j=0; j<enNote.getResourcesSize() && keepRunning; j++) {\r
+ Resource newRes = rl.get(j);\r
+ Data d = newRes.getData();\r
+ if (d!=null) { \r
+ logger.log(logger.EXTREME, "Calculating resource hash");\r
+ String hash = byteArrayToHexString(d.getBodyHash());\r
+ logger.log(logger.EXTREME, "updating resources by hash");\r
+ String oldGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(enNote.getGuid(), hash);\r
+ conn.getNoteTable().updateNoteResourceGuidbyHash(enNote.getGuid(), newRes.getGuid(), hash);\r
+ resourceSignal.resourceGuidChanged.emit(enNote.getGuid(), oldGuid, newRes.getGuid());\r
}\r
- logger.log(logger.EXTREME, "Resetting note dirty flag");\r
- conn.getNoteTable().resetDirtyFlag(enNote.getGuid());\r
- updateSequenceNumber = enNote.getUpdateSequenceNum();\r
- logger.log(logger.EXTREME, "Emitting note sequence number change");\r
- conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
-\r
- } catch (EDAMUserException e) {\r
- logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotes "+e);\r
- status.message.emit(tr("Error sending local note: ") +e.getParameter());\r
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- } catch (EDAMSystemException e) {\r
- logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotes "+e);\r
- status.message.emit(tr("Error: ") +e);\r
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- } catch (EDAMNotFoundException e) {\r
- logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalNotes " +e);\r
- status.message.emit(tr("Error sending local note: ") +e);\r
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
- } catch (TException e) {\r
- logger.log(logger.LOW, "*** EDAM TExcepton syncLocalNotes "+e);\r
- status.message.emit(tr("Error sending local note: ") +e);\r
- logger.log(logger.LOW, e.toString()); \r
- error = true;\r
}\r
+ logger.log(logger.EXTREME, "Resetting note dirty flag");\r
+ conn.getNoteTable().resetDirtyFlag(enNote.getGuid());\r
+ updateSequenceNumber = enNote.getUpdateSequenceNum();\r
+ logger.log(logger.EXTREME, "Emitting note sequence number change");\r
+ conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
+\r
+ } catch (EDAMUserException e) {\r
+ logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotes "+e);\r
+ status.message.emit(tr("Error sending local note: ") +e.getParameter());\r
+ logger.log(logger.LOW, e.toString()); \r
+ error = true;\r
+ } catch (EDAMSystemException e) {\r
+ logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotes "+e);\r
+ status.message.emit(tr("Error: ") +e);\r
+ logger.log(logger.LOW, e.toString()); \r
+ error = true;\r
+ } catch (EDAMNotFoundException e) {\r
+ logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalNotes " +e);\r
+ status.message.emit(tr("Error sending local note: ") +e);\r
+ logger.log(logger.LOW, e.toString()); \r
+ error = true;\r
+ } catch (TException e) {\r
+ logger.log(logger.LOW, "*** EDAM TExcepton syncLocalNotes "+e);\r
+ status.message.emit(tr("Error sending local note: ") +e);\r
+ logger.log(logger.LOW, e.toString()); \r
+ error = true;\r
}\r
}\r
- logger.log(logger.HIGH, "Entering SyncRunner.syncNotes");\r
+ logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalNote");\r
\r
}\r
+\r
// Sync Notebooks with Evernote\r
private void syncLocalNotebooks() {\r
logger.log(logger.HIGH, "Entering SyncRunner.syncLocalNotebooks");\r
for (int i=0; i<notebooks.size() && keepRunning; i++) {\r
\r
if (authRefreshNeeded)\r
- refreshConnection();\r
+ if (!refreshConnection())\r
+ return;\r
\r
Notebook enNotebook = notebooks.get(i);\r
try {\r
Tag enTag = findNextTag();\r
while(enTag!=null) {\r
if (authRefreshNeeded)\r
- refreshConnection();\r
+ if (!refreshConnection())\r
+ return;\r
\r
try {\r
if (enTag.getUpdateSequenceNum() > 0) {\r
}\r
logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalTags");\r
}\r
- // Sync Tags with Evernote\r
+ private void syncLocalLinkedNotebooks() {\r
+ logger.log(logger.HIGH, "Entering SyncRunner.syncLocalLinkedNotebooks");\r
+ \r
+ List<String> list = conn.getLinkedNotebookTable().getDirtyGuids();\r
+ for (int i=0; i<list.size(); i++) {\r
+ LinkedNotebook book = conn.getLinkedNotebookTable().getNotebook(list.get(i));\r
+ try {\r
+ noteStore.updateLinkedNotebook(authToken, book);\r
+ } catch (EDAMUserException e) {\r
+ logger.log(logger.LOW, "*** EDAM User Excepton syncLocalLinkedNotebooks");\r
+ status.message.emit(tr("Error: ") +e);\r
+ logger.log(logger.LOW, e.toString()); \r
+ error = true;\r
+ e.printStackTrace();\r
+ } catch (EDAMNotFoundException e) {\r
+ logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalLinkedNotebooks");\r
+ status.message.emit(tr("Error: ") +e);\r
+ logger.log(logger.LOW, e.toString()); \r
+ error = true;\r
+ e.printStackTrace();\r
+ } catch (EDAMSystemException e) {\r
+ logger.log(logger.LOW, "*** EDAM System Excepton syncLocalLinkedNotebooks");\r
+ status.message.emit(tr("Error: ") +e);\r
+ logger.log(logger.LOW, e.toString()); \r
+ error = true;\r
+ e.printStackTrace();\r
+ } catch (TException e) {\r
+ logger.log(logger.LOW, "*** EDAM TExcepton syncLocalLinkedNotebooks");\r
+ status.message.emit(tr("Error: ") +e);\r
+ logger.log(logger.LOW, e.toString()); \r
+ error = true;\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalLinkedNotebooks");\r
+ }\r
+ // Sync Saved Searches with Evernote\r
private void syncLocalSavedSearches() {\r
logger.log(logger.HIGH, "Entering SyncRunner.syncLocalSavedSearches");\r
List<SavedSearch> remoteList = new ArrayList<SavedSearch>();\r
for (int i=0; i<searches.size() && keepRunning; i++) {\r
\r
if (authRefreshNeeded)\r
- refreshConnection();\r
+ if (!refreshConnection())\r
+ return;\r
\r
SavedSearch enSearch = searches.get(i);\r
try {\r
while(more && keepRunning) {\r
\r
if (authRefreshNeeded)\r
- refreshConnection();\r
+ if (!refreshConnection())\r
+ return;\r
\r
chunk = null;\r
int sequence = updateSequenceNumber;\r
syncRemoteTags(chunk.getTags());\r
syncRemoteSavedSearches(chunk.getSearches());\r
syncRemoteNotebooks(chunk.getNotebooks());\r
- syncRemoteNotes(chunk.getNotes(), fullSync);\r
+ syncRemoteNotes(chunk.getNotes(), fullSync, authToken);\r
syncRemoteResources(chunk.getResources());\r
+ syncRemoteLinkedNotebooks(chunk.getLinkedNotebooks());\r
+ syncExpungedNotes(chunk);\r
\r
- // Do the local deletes\r
- logger.log(logger.EXTREME, "Doing local deletes");\r
- List<String> guid = chunk.getExpungedNotes();\r
- if (guid != null) \r
- for (int i=0; i<guid.size() && keepRunning; i++) {\r
- logger.log(logger.EXTREME, "Expunging local note from database");\r
- conn.getNoteTable().expungeNote(guid.get(i), true, false);\r
- }\r
- guid = chunk.getExpungedNotebooks();\r
- if (guid != null)\r
- for (int i=0; i<guid.size() && keepRunning; i++) {\r
- logger.log(logger.EXTREME, "Expunging local notebook from database");\r
- conn.getNotebookTable().expungeNotebook(guid.get(i), false);\r
- }\r
- guid = chunk.getExpungedTags();\r
- if (guid != null)\r
- for (int i=0; i<guid.size() && keepRunning; i++) {\r
- logger.log(logger.EXTREME, "Expunging tags from local database");\r
- conn.getTagTable().expungeTag(guid.get(i), false);\r
- }\r
- guid = chunk.getExpungedSearches();\r
- if (guid != null) \r
- for (int i=0; i<guid.size() && keepRunning; i++) {\r
- logger.log(logger.EXTREME, "Expunging saved search from local database");\r
- conn.getSavedSearchTable().expungeSavedSearch(guid.get(i), false);\r
- }\r
-\r
\r
// Check for more notes\r
if (chunk.getChunkHighUSN() <= updateSequenceNumber) \r
\r
logger.log(logger.HIGH, "Leaving SyncRunner.syncRemoteToLocal");\r
}\r
+ // Sync expunged notes\r
+ private void syncExpungedNotes(SyncChunk chunk) {\r
+ // Do the local deletes\r
+ logger.log(logger.EXTREME, "Doing local deletes");\r
+ List<String> guid = chunk.getExpungedNotes();\r
+ if (guid != null) {\r
+ for (int i=0; i<guid.size() && keepRunning; i++) {\r
+ String notebookGuid = "";\r
+ Note localNote = conn.getNoteTable().getNote(guid.get(i), false, false, false, false, false);\r
+ if (localNote != null) {\r
+ conn.getNoteTable().updateNoteSequence(guid.get(i), 0);\r
+ notebookGuid = localNote.getNotebookGuid();\r
+ }\r
+ if (!conn.getNotebookTable().isNotebookLocal(notebookGuid)) {\r
+ logger.log(logger.EXTREME, "Expunging local note from database");\r
+ conn.getNoteTable().expungeNote(guid.get(i), true, false);\r
+ }\r
+ }\r
+ }\r
+ guid = chunk.getExpungedNotebooks();\r
+ if (guid != null)\r
+ for (int i=0; i<guid.size() && keepRunning; i++) {\r
+ logger.log(logger.EXTREME, "Expunging local notebook from database");\r
+ conn.getNotebookTable().expungeNotebook(guid.get(i), false);\r
+ }\r
+ guid = chunk.getExpungedTags();\r
+ if (guid != null)\r
+ for (int i=0; i<guid.size() && keepRunning; i++) {\r
+ logger.log(logger.EXTREME, "Expunging tags from local database");\r
+ conn.getTagTable().expungeTag(guid.get(i), false);\r
+ }\r
+ guid = chunk.getExpungedSearches();\r
+ if (guid != null) \r
+ for (int i=0; i<guid.size() && keepRunning; i++) {\r
+ logger.log(logger.EXTREME, "Expunging saved search from local database");\r
+ conn.getSavedSearchTable().expungeSavedSearch(guid.get(i), false);\r
+ }\r
+ guid = chunk.getExpungedLinkedNotebooks();\r
+ if (guid != null) \r
+ for (int i=0; i<guid.size() && keepRunning; i++) {\r
+ logger.log(logger.EXTREME, "Expunging linked notebook from local database");\r
+ conn.getLinkedNotebookTable().expungeNotebook(guid.get(i), false);\r
+ }\r
+\r
+ }\r
// Sync remote tags\r
private void syncRemoteTags(List<Tag> tags) {\r
logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteTags");\r
}\r
logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteTags");\r
}\r
- // Sync remote tags\r
+ // Sync remote saved searches\r
private void syncRemoteSavedSearches(List<SavedSearch> searches) {\r
logger.log(logger.EXTREME, "Entering SyncRunner.syncSavedSearches");\r
if (searches != null) {\r
}\r
logger.log(logger.EXTREME, "Leaving SyncRunner.syncSavedSearches");\r
}\r
+ // Sync remote linked notebooks\r
+ private void syncRemoteLinkedNotebooks(List<LinkedNotebook> books) {\r
+ logger.log(logger.EXTREME, "Entering SyncRunner.syncLinkedNotebooks");\r
+ if (books != null) {\r
+ for (int i=0; i<books.size() && keepRunning; i++) {\r
+ conn.getLinkedNotebookTable().updateNotebook(books.get(i), false); \r
+ }\r
+ }\r
+ logger.log(logger.EXTREME, "Leaving SyncRunner.syncLinkedNotebooks");\r
+ }\r
// Sync remote Notebooks 2\r
private void syncRemoteNotebooks(List<Notebook> notebooks) {\r
logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotebooks");\r
if (oldGuid != null && !conn.getNotebookTable().isNotebookLocal(oldGuid) && !notebooks.get(i).getGuid().equalsIgnoreCase(oldGuid))\r
conn.getNotebookTable().updateNotebookGuid(oldGuid, notebooks.get(i).getGuid());\r
conn.getNotebookTable().syncNotebook(notebooks.get(i), false); \r
+ \r
+ // Synchronize shared notebook information\r
+// if (notebooks.get(i).getSharedNotebookIdsSize() > 0) {\r
+// conn.getSharedNotebookTable().expungeNotebookByGuid(notebooks.get(i).getGuid(), false);\r
+// for (int j=0; j<notebooks.get(i).getSharedNotebookIdsSize(); j++) {\r
+// syncRemoteSharedNotebook(notebooks.get(i).getGuid(), notebooks.get(i).getSharedNotebookIds().get(j), authToken);\r
+// }\r
+// }\r
}\r
} \r
logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteNotebooks");\r
}\r
+ // Sync remote shared notebook\r
+// private void syncRemoteSharedNotebook(String guid, Long id, String token) {\r
+// List<SharedNotebook> books = noteStore.getSharedNotebookByAuth(authToken);\r
+// }\r
// Sync remote Resources\r
private void syncRemoteResources(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
+ }\r
+ }\r
+ logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteResources");\r
+ }\r
+ // Sync remote resource\r
+ private void syncRemoteResource(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
// 3.) If a copy of the resource is in the local databbase and it is dirty and the hash doesn't match, we ignore it because there\r
// is a conflict. The note conflict should get a copy of the resource at that time.\r
\r
- logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteResources");\r
- if (resource != null) {\r
- for (int i=0; i<resource.size() && keepRunning; i++) {\r
- boolean saveNeeded = false;\r
-/* #1 */ Resource r = getEvernoteResource(resource.get(i).getGuid(), true,true,true);\r
- Resource l = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), false);\r
- if (l == null) {\r
- saveNeeded = true;\r
- } else {\r
-/* #2 */ boolean isNoteDirty = conn.getNoteTable().isNoteDirty(r.getNoteGuid());\r
- if (!isNoteDirty)\r
- saveNeeded = true;\r
- else {\r
-/* #3 */ String remoteHash = "";\r
- if (r != null && r.getData() != null && r.getData().getBodyHash() != null)\r
- remoteHash = byteArrayToHexString(r.getData().getBodyHash());\r
- String localHash = "";\r
- if (l != null && l.getData() != null && l.getData().getBodyHash() != null)\r
- remoteHash = byteArrayToHexString(l.getData().getBodyHash());\r
- \r
- if (localHash.equalsIgnoreCase(remoteHash))\r
+ boolean saveNeeded = false;\r
+ /* #1 */ Resource r = getEvernoteResource(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
- \r
- if (saveNeeded) \r
- conn.getNoteTable().noteResourceTable.updateNoteResource(r, false);\r
+ } else {\r
+ /* #2 */ boolean isNoteDirty = conn.getNoteTable().isNoteDirty(r.getNoteGuid());\r
+ if (!isNoteDirty)\r
+ saveNeeded = true;\r
+ else {\r
+ /* #3 */ String remoteHash = "";\r
+ if (r != null && r.getData() != null && r.getData().getBodyHash() != null)\r
+ remoteHash = byteArrayToHexString(r.getData().getBodyHash());\r
+ String localHash = "";\r
+ if (l != null && l.getData() != null && l.getData().getBodyHash() != null)\r
+ remoteHash = byteArrayToHexString(l.getData().getBodyHash());\r
+ \r
+ if (localHash.equalsIgnoreCase(remoteHash))\r
+ saveNeeded = true;\r
+ }\r
+ }\r
+ \r
+ if (saveNeeded) \r
+ conn.getNoteTable().noteResourceTable.updateNoteResource(r, false);\r
+ if (r.getMime().equalsIgnoreCase("application/vnd.evernote.ink"))\r
+ downloadInkNoteImage(r.getGuid(), authToken);\r
\r
- }\r
- }\r
- logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteResources");\r
}\r
- // Sync remote notebooks\r
- private void syncRemoteNotes(List<Note> note, boolean fullSync) {\r
+ // Sync remote notes\r
+ private void syncRemoteNotes(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);\r
- if (n!=null) {\r
- \r
- // Basically, this is how the sync logic for a note works.\r
- // If the remote note has changed and the local has not, we\r
- // accept the change.\r
- // If both the local & remote have changed but the sequence\r
- // numbers are the same, we don't accept the change. This\r
- // seems to happen when attachments are indexed by the server.\r
- // If both the local & remote have changed and the sequence numbers\r
- // are different we move the local copy to a local notebook (making sure\r
- // to copy all resources) and we accept the new one. \r
- boolean conflictingNote = true;\r
- logger.log(logger.EXTREME, "Checking for duplicate note " +n.getGuid());\r
- if (dirtyNoteGuids.contains(n.getGuid())) { \r
- logger.log(logger.EXTREME, "Conflict check beginning");\r
- conflictingNote = checkForConflict(n);\r
- logger.log(logger.EXTREME, "Conflict check results " +conflictingNote);\r
- if (conflictingNote)\r
- moveConflictingNote(n.getGuid());\r
- }\r
- if (conflictingNote || fullSync) {\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
- 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
- for (int q=0; q<n.getResources().size() && keepRunning; q++) {\r
- logger.log(logger.EXTREME, "Getting note resources.");\r
- conn.getNoteTable().noteResourceTable.updateNoteResource(n.getResources().get(q), false);\r
- }\r
- }\r
+ Note n = getEvernoteNote(note.get(i).getGuid(), true, fullSync, true,true, token);\r
+ syncRemoteNote(n, fullSync, token);\r
+ }\r
+ }\r
+ logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteNotes");\r
+ }\r
+ private void syncRemoteNote(Note n, boolean fullSync, String token) {\r
+ if (n!=null) {\r
+ \r
+ // Basically, this is how the sync logic for a note works.\r
+ // If the remote note has changed and the local has not, we\r
+ // accept the change.\r
+ // If both the local & remote have changed but the sequence\r
+ // numbers are the same, we don't accept the change. This\r
+ // seems to happen when attachments are indexed by the server.\r
+ // If both the local & remote have changed and the sequence numbers\r
+ // are different we move the local copy to a local notebook (making sure\r
+ // to copy all resources) and we accept the new one. \r
+ boolean conflictingNote = true;\r
+ logger.log(logger.EXTREME, "Checking for duplicate note " +n.getGuid());\r
+ if (dirtyNoteGuids != null && dirtyNoteGuids.contains(n.getGuid())) { \r
+ logger.log(logger.EXTREME, "Conflict check beginning");\r
+ conflictingNote = checkForConflict(n);\r
+ logger.log(logger.EXTREME, "Conflict check results " +conflictingNote);\r
+ if (conflictingNote)\r
+ moveConflictingNote(n.getGuid());\r
+ }\r
+ boolean ignoreNote = false;\r
+ if (ignoreNotebooks.contains(n.getNotebookGuid()))\r
+ ignoreNote = true;\r
+ for (int i=0; i<n.getTagGuidsSize(); i++) {\r
+ if (ignoreTags.contains(n.getTagGuids().get(i))) {\r
+ ignoreNote = true;\r
+ i=n.getTagGuidsSize();\r
+ }\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
+ 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
+ for (int q=0; q<n.getResources().size() && keepRunning; q++) {\r
+ logger.log(logger.EXTREME, "Getting note resources.");\r
+ conn.getNoteTable().noteResourceTable.updateNoteResource(n.getResources().get(q), false);\r
+ if (n.getResources().get(q).getMime().equalsIgnoreCase("application/vnd.evernote.ink"))\r
+ downloadInkNoteImage(n.getResources().get(q).getGuid(), token);\r
}\r
}\r
}\r
}\r
- logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteNotes");\r
}\r
- private Note getEvernoteNote(String guid, boolean withContent, boolean withResourceData, boolean withResourceRecognition, boolean withResourceAlternateData) { \r
+ private Note getEvernoteNote(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
- n = noteStore.getNote(authToken, guid, withContent, withResourceData, withResourceRecognition, withResourceAlternateData);\r
+ n = noteStore.getNote(token, guid, withContent, withResourceData, withResourceRecognition, withResourceAlternateData);\r
logger.log(logger.EXTREME, "Note " +guid +" has been retrieved.");\r
} catch (EDAMUserException e) {\r
logger.log(logger.LOW, "*** EDAM User Excepton getEvernoteNote");\r
}\r
return n;\r
}\r
- private Resource getEvernoteResource(String guid, boolean withData, boolean withRecognition, boolean withAttributes) { \r
+ private Resource getEvernoteResource(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
- n = noteStore.getResource(authToken, guid, withData, withRecognition, withAttributes, withAttributes);\r
+ n = noteStore.getResource(token, guid, withData, withRecognition, withAttributes, withAttributes);\r
logger.log(logger.EXTREME, "Resource " +guid +" has been retrieved.");\r
} catch (EDAMUserException e) {\r
logger.log(logger.LOW, "*** EDAM User Excepton getEvernoteNote");\r
newBook.setPublished(false);\r
\r
conn.getNotebookTable().addNotebook(newBook, false, true);\r
+ notebookSignal.listChanged.emit();\r
notebookGuid = newBook.getGuid();\r
+ refreshNeeded = true;\r
}\r
\r
// Now that we have a good notebook guid, we need to move the conflicting note\r
conn.getNoteTable().updateNoteGuid(guid, newGuid);\r
conn.getNoteTable().updateNoteNotebook(newGuid, notebookGuid, true);\r
\r
- \r
+ noteSignal.notebookChanged.emit(newGuid, notebookGuid);\r
+ refreshNeeded = true;\r
noteSignal.guidChanged.emit(guid,newGuid);\r
}\r
\r
- \r
+\r
\r
\r
//******************************************************\r
\r
boolean versionOk = false;\r
try {\r
-// versionOk = userStore.checkVersion("Dave's EDAMDemo (Java)", \r
versionOk = userStore.checkVersion("NeverNote", \r
com.evernote.edam.userstore.Constants.EDAM_VERSION_MAJOR, \r
com.evernote.edam.userstore.Constants.EDAM_VERSION_MINOR);\r
isConnected = false;\r
}\r
// Refresh the connection\r
- private synchronized void refreshConnection() {\r
+ private synchronized boolean refreshConnection() {\r
logger.log(logger.EXTREME, "Entering SyncRunner.refreshConnection()");\r
// Calendar cal = Calendar.getInstance();\r
\r
// If we are not connected let's get out of here\r
if (!isConnected)\r
- return;\r
+ return false;\r
\r
// If we fail too many times, then let's give up.\r
if (failedRefreshes >=5) {\r
logger.log(logger.EXTREME, "Refresh attempts have failed. Disconnecting.");\r
isConnected = false;\r
- return;\r
+ status.message.emit(tr("Unable to synchronize - Authentication failed"));\r
+ return false;\r
}\r
\r
// If this is the first time through, then we need to set this\r
if (userStore != null && authToken != null) \r
newAuth = userStore.refreshAuthentication(authToken); \r
else\r
- return;\r
+ return false;\r
logger.log(logger.EXTREME, "UserStore.refreshAuthentication has succeeded.");\r
} catch (EDAMUserException e) {\r
e.printStackTrace();\r
syncSignal.authRefreshComplete.emit(false);\r
failedRefreshes++;\r
- return;\r
+ return false;\r
} catch (EDAMSystemException e) {\r
e.printStackTrace();\r
syncSignal.authRefreshComplete.emit(false);\r
failedRefreshes++;\r
- return; \r
+ return false; \r
} catch (TException e) { \r
e.printStackTrace();\r
syncSignal.authRefreshComplete.emit(false);\r
failedRefreshes++;\r
- return;\r
+ return false;\r
}\r
\r
// If we didn't get a good auth, then we've failed\r
if (newAuth == null) {\r
failedRefreshes++;\r
+ status.message.emit(tr("Unable to synchronize - Authentication failed"));\r
logger.log(logger.EXTREME, "Authentication failure #" +failedRefreshes);\r
+ status.message.emit(tr("Unable to synchronize - Authentication failed"));\r
syncSignal.authRefreshComplete.emit(false);\r
- return;\r
+ return false;\r
}\r
\r
// We got a good token. Now we need to setup the time to renew it.\r
// failedRefreshes++;\r
// syncSignal.authRefreshComplete.emit(false);\r
// }\r
+ \r
+ return true;\r
}\r
- \r
+ \r
public synchronized boolean addWork(String request) {\r
if (workQueue.offer(request))\r
return true;\r
n.setContent(conn.getNoteTable().getNoteContentBinary(n.getGuid()));\r
return n;\r
}\r
+\r
+\r
+\r
+ //*********************************************************\r
+ //* Special download instructions. Used for DB upgrades\r
+ //*********************************************************\r
+ private void downloadAllSharedNotebooks() {\r
+ try {\r
+ List<SharedNotebook> books = noteStore.listSharedNotebooks(authToken);\r
+ logger.log(logger.LOW, "Shared notebooks found = " +books.size());\r
+ for (int i=0; i<books.size(); i++) {\r
+ conn.getSharedNotebookTable().updateNotebook(books.get(i), false);\r
+ }\r
+ conn.getSyncTable().deleteRecord("FullSharedNotebookSync");\r
+ } catch (EDAMUserException e1) {\r
+ e1.printStackTrace();\r
+ status.message.emit(tr("User exception Listing shared notebooks."));\r
+ logger.log(logger.LOW, e1.getMessage());\r
+ return;\r
+ } catch (EDAMSystemException e1) {\r
+ e1.printStackTrace();\r
+ status.message.emit(tr("System exception Listing shared notebooks."));\r
+ logger.log(logger.LOW, e1.getMessage());\r
+ return;\r
+ } catch (TException e1) {\r
+ e1.printStackTrace();\r
+ status.message.emit(tr("Transaction exception Listing shared notebooks."));\r
+ logger.log(logger.LOW, e1.getMessage());\r
+ return;\r
+ } catch (EDAMNotFoundException e1) {\r
+ e1.printStackTrace();\r
+ status.message.emit(tr("EDAM Not Found exception Listing shared notebooks."));\r
+ logger.log(logger.LOW, e1.getMessage());\r
+ }\r
+ }\r
+ private void downloadAllNotebooks() {\r
+ try {\r
+ List<Notebook> books = noteStore.listNotebooks(authToken);\r
+ logger.log(logger.LOW, "Shared notebooks found = " +books.size());\r
+ for (int i=0; i<books.size(); i++) {\r
+ conn.getNotebookTable().updateNotebook(books.get(i), false);\r
+ }\r
+ conn.getSyncTable().deleteRecord("FullNotebookSync");\r
+ } catch (EDAMUserException e1) {\r
+ e1.printStackTrace();\r
+ status.message.emit(tr("User exception Listing notebooks."));\r
+ logger.log(logger.LOW, e1.getMessage());\r
+ return;\r
+ } catch (EDAMSystemException e1) {\r
+ e1.printStackTrace();\r
+ status.message.emit(tr("System exception Listing notebooks."));\r
+ logger.log(logger.LOW, e1.getMessage());\r
+ return;\r
+ } catch (TException e1) {\r
+ e1.printStackTrace();\r
+ status.message.emit(tr("Transaction exception Listing notebooks."));\r
+ logger.log(logger.LOW, e1.getMessage());\r
+ return;\r
+ }\r
+ }\r
+ private void downloadAllLinkedNotebooks() {\r
+ try {\r
+ List<LinkedNotebook> books = noteStore.listLinkedNotebooks(authToken);\r
+ logger.log(logger.LOW, "Linked notebooks found = " +books.size());\r
+ for (int i=0; i<books.size(); i++) {\r
+ conn.getLinkedNotebookTable().updateNotebook(books.get(i), false);\r
+ }\r
+ conn.getSyncTable().deleteRecord("FullLinkedNotebookSync");\r
+ } catch (EDAMUserException e1) {\r
+ e1.printStackTrace();\r
+ status.message.emit(tr("User exception Listing linked notebooks."));\r
+ logger.log(logger.LOW, e1.getMessage());\r
+ return;\r
+ } catch (EDAMSystemException e1) {\r
+ e1.printStackTrace();\r
+ status.message.emit(tr("System exception Listing linked notebooks."));\r
+ logger.log(logger.LOW, e1.getMessage());\r
+ return;\r
+ } catch (TException e1) {\r
+ e1.printStackTrace();\r
+ status.message.emit(tr("Transaction exception Listing lineked notebooks."));\r
+ logger.log(logger.LOW, e1.getMessage());\r
+ return;\r
+ } catch (EDAMNotFoundException e1) {\r
+ e1.printStackTrace();\r
+ status.message.emit(tr("EDAM Not Found exception Listing linked notebooks."));\r
+ logger.log(logger.LOW, e1.getMessage());\r
+ }\r
+ }\r
+\r
+ \r
+ private void downloadInkNoteImage(String guid, String authToken) {\r
+ String urlBase = noteStoreUrl.replace("/edam/note/", "/shard/") + "/res/"+guid+".ink?slice=";\r
+// urlBase = "https://www.evernote.com/shard/s1/res/52b567a9-54ae-4a08-afc5-d5bae275b2a8.ink?slice=";\r
+ Integer slice = 1;\r
+ Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, false);\r
+ conn.getInkImagesTable().expungeImage(r.getGuid());\r
+ int sliceCount = 1+((r.getHeight()-1)/480);\r
+ HttpClient http = new DefaultHttpClient();\r
+ for (int i=0; i<sliceCount; i++) {\r
+ String url = urlBase + slice.toString();\r
+ HttpPost post = new HttpPost(url);\r
+ post.getParams().setParameter("auth", authToken);\r
+ List <NameValuePair> nvps = new ArrayList <NameValuePair>();\r
+ nvps.add(new BasicNameValuePair("auth", authToken));\r
+\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
+ HttpResponse response = http.execute(post);\r
+ HttpEntity resEntity = response.getEntity();\r
+ InputStream is = resEntity.getContent();\r
+ QByteArray data = writeToFile(is);\r
+ conn.getInkImagesTable().saveImage(guid, slice, data);\r
+ } catch (ClientProtocolException e) {\r
+ e.printStackTrace();\r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ }\r
+\r
+ slice++;\r
+ }\r
+ http.getConnectionManager().shutdown(); \r
+ noteSignal.noteChanged.emit(r.getNoteGuid(), null); // Signal to ivalidate note cache\r
+ }\r
+ \r
+ \r
+ public QByteArray writeToFile(InputStream iStream) throws IOException {\r
+\r
+ File temp = File.createTempFile("nn-inknote-temp", ".png");\r
+\r
+ // Save InputStream to the file.\r
+ BufferedOutputStream fOut = null;\r
+ try {\r
+ fOut = new BufferedOutputStream(new FileOutputStream(temp));\r
+ byte[] buffer = new byte[32 * 1024];\r
+ int bytesRead = 0;\r
+ while ((bytesRead = iStream.read(buffer)) != -1) {\r
+ fOut.write(buffer, 0, bytesRead);\r
+ }\r
+ }\r
+ finally {\r
+ iStream.close();\r
+ fOut.close();\r
+ }\r
+ QFile tempFile = new QFile(temp.getAbsoluteFile().toString());\r
+ tempFile.open(OpenModeFlag.ReadOnly);\r
+ QByteArray data = tempFile.readAll();\r
+ tempFile.close();\r
+ tempFile.remove();\r
+ return data;\r
+ }\r
+ \r
+ \r
+ //******************************************\r
+ //* Begin syncing shared notebooks \r
+ //******************************************\r
+ private void syncLinkedNotebooks() {\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
+ for (int i=0; i<books.size(); i++) {\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
+ SyncState linkedSyncState = \r
+ noteStore.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
+ }\r
+ \r
+ // Synchronize local changes\r
+ syncLocalLinkedNoteChanges(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
+ error = true;\r
+ e.printStackTrace();\r
+ } catch (EDAMSystemException 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
+ // Cleanup tags\r
+ conn.getTagTable().removeUnusedLinkedTags();\r
+ conn.getTagTable().cleanupTags();\r
+ tagSignal.listChanged.emit();\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
+ List<Note> dirtyNotes = conn.getNoteTable().getDirtyLinkedNotes();\r
+ if (dirtyNoteGuids == null) \r
+ dirtyNoteGuids = new Vector<String>();\r
+\r
+ for (int i=0; i<dirtyNotes.size() && keepRunning; i++) {\r
+ dirtyNoteGuids.add(dirtyNotes.get(i).getGuid());\r
+ }\r
+ boolean fullSync = false;\r
+ if (usn == 0)\r
+ fullSync = true;\r
+ while (usn < highSequence) {\r
+ try {\r
+ SyncChunk chunk = \r
+ noteStore.getLinkedNotebookSyncChunk(authToken, book, usn, 10, fullSync);\r
+\r
+ if (!ignoreLinkedNotebooks.contains(book.getGuid()))\r
+ syncRemoteNotes(chunk.getNotes(), fullSync, linkedAuthResult.getAuthenticationToken());\r
+ findNewLinkedTags(chunk.getNotes(), linkedAuthResult.getAuthenticationToken());\r
+ for (int i=0; i<chunk.getResourcesSize(); i++) {\r
+ syncRemoteResource(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
+ \r
+ \r
+ // Expunge records\r
+ for (int i=0; i<chunk.getExpungedLinkedNotebooksSize(); i++) {\r
+ conn.getLinkedNotebookTable().expungeNotebook(chunk.getExpungedLinkedNotebooks().get(i), false);\r
+ }\r
+ usn = chunk.getChunkHighUSN();\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
+ 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
+ // Sync remote tags\r
+ private void syncLinkedTags(List<Tag> tags, String notebookGuid) {\r
+ logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteTags");\r
+ if (tags != null) {\r
+ for (int i=0; i<tags.size() && keepRunning; i++) {\r
+ conn.getTagTable().syncLinkedTag(tags.get(i), notebookGuid, false);\r
+ }\r
+ }\r
+ logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteTags");\r
+ }\r
+ \r
+ // Sync notebooks from a linked notebook\r
+ private void syncRemoteLinkedNotebooks(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
+ notebooks.get(i).setName(linked.getShareName());\r
+ notebooks.get(i).setDefaultNotebook(false);\r
+ conn.getNotebookTable().syncLinkedNotebook(notebooks.get(i), false, readOnly); \r
+ } catch (EDAMUserException e) {\r
+ readOnly = true;\r
+ e.printStackTrace();\r
+ } catch (EDAMNotFoundException e) {\r
+ readOnly = true;\r
+ e.printStackTrace();\r
+ } catch (EDAMSystemException e) {\r
+ readOnly = true;\r
+ e.printStackTrace();\r
+ } catch (TException e) {\r
+ readOnly = true;\r
+ e.printStackTrace();\r
+ }\r
+\r
+ }\r
+ } \r
+ logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteNotebooks");\r
+ }\r
+\r
+ private void findNewLinkedTags(List<Note> newNotes, String token) {\r
+ if (newNotes == null)\r
+ return;\r
+ for (int i=0; i<newNotes.size(); i++) {\r
+ Note n = newNotes.get(i);\r
+ for (int j=0; j<n.getTagGuidsSize(); j++) {\r
+ String tag = n.getTagGuids().get(j);\r
+ if (!conn.getTagTable().exists(tag)) {\r
+ Tag newTag;\r
+ try {\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
+ }\r
+ }\r
+\r
+ // Synchronize changes locally done to linked notes\r
+ private void syncLocalLinkedNoteChanges(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
+ }\r
+ }\r
+\r
}\r