OSDN Git Service

Upgrade to evernote-1.17.
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / threads / SyncRunner.java
1 /*\r
2  * This file is part of NeverNote \r
3  * Copyright 2009 Randy Baumgarte\r
4  * \r
5  * This file may be licensed under the terms of of the\r
6  * GNU General Public License Version 2 (the ``GPL'').\r
7  *\r
8  * Software distributed under the License is distributed\r
9  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either\r
10  * express or implied. See the GPL for the specific language\r
11  * governing rights and limitations.\r
12  *\r
13  * You should have received a copy of the GPL along with this\r
14  * program. If not, go to http://www.gnu.org/licenses/gpl.html\r
15  * or write to the Free Software Foundation, Inc.,\r
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
17  *\r
18 */\r
19 package cx.fbn.nevernote.threads;\r
20 \r
21 import java.net.UnknownHostException;\r
22 import java.util.ArrayList;\r
23 import java.util.Calendar;\r
24 import java.util.Date;\r
25 import java.util.GregorianCalendar;\r
26 import java.util.List;\r
27 import java.util.Vector;\r
28 import java.util.concurrent.LinkedBlockingQueue;\r
29 \r
30 import org.apache.thrift.TException;\r
31 import org.apache.thrift.protocol.TBinaryProtocol;\r
32 import org.apache.thrift.transport.THttpClient;\r
33 import org.apache.thrift.transport.TTransportException;\r
34 \r
35 import com.evernote.edam.error.EDAMNotFoundException;\r
36 import com.evernote.edam.error.EDAMSystemException;\r
37 import com.evernote.edam.error.EDAMUserException;\r
38 import com.evernote.edam.notestore.NoteStore;\r
39 import com.evernote.edam.notestore.SyncChunk;\r
40 import com.evernote.edam.notestore.SyncState;\r
41 import com.evernote.edam.type.Data;\r
42 import com.evernote.edam.type.LinkedNotebook;\r
43 import com.evernote.edam.type.Note;\r
44 import com.evernote.edam.type.Notebook;\r
45 import com.evernote.edam.type.Resource;\r
46 import com.evernote.edam.type.SavedSearch;\r
47 import com.evernote.edam.type.SharedNotebook;\r
48 import com.evernote.edam.type.Tag;\r
49 import com.evernote.edam.type.User;\r
50 import com.evernote.edam.userstore.AuthenticationResult;\r
51 import com.evernote.edam.userstore.UserStore;\r
52 import com.trolltech.qt.core.QObject;\r
53 import com.trolltech.qt.gui.QMessageBox;\r
54 \r
55 import cx.fbn.nevernote.signals.NoteIndexSignal;\r
56 import cx.fbn.nevernote.signals.NoteResourceSignal;\r
57 import cx.fbn.nevernote.signals.NoteSignal;\r
58 import cx.fbn.nevernote.signals.NotebookSignal;\r
59 import cx.fbn.nevernote.signals.SavedSearchSignal;\r
60 import cx.fbn.nevernote.signals.StatusSignal;\r
61 import cx.fbn.nevernote.signals.SyncSignal;\r
62 import cx.fbn.nevernote.signals.TagSignal;\r
63 import cx.fbn.nevernote.sql.DatabaseConnection;\r
64 import cx.fbn.nevernote.sql.DeletedItemRecord;\r
65 import cx.fbn.nevernote.utilities.ApplicationLogger;\r
66 \r
67 public class SyncRunner extends QObject implements Runnable {\r
68         \r
69         private final ApplicationLogger logger;\r
70                 private DatabaseConnection              conn;\r
71                 private boolean                                 idle;\r
72                 public boolean                                  error;\r
73                 public volatile boolean                 isConnected;\r
74                 public volatile boolean                 keepRunning;\r
75                 public volatile String                  authToken;\r
76                 private long                                    evernoteUpdateCount;\r
77                 \r
78                 public volatile NoteStore.Client                noteStore;\r
79                 private UserStore.Client                                userStore;\r
80                 \r
81                 public volatile StatusSignal                    status;\r
82                 public volatile TagSignal                               tagSignal;\r
83                 public volatile NotebookSignal                  notebookSignal;\r
84                 public volatile NoteIndexSignal                 noteIndexSignal;\r
85                 public volatile NoteSignal                              noteSignal;\r
86                 public volatile SavedSearchSignal               searchSignal;\r
87                 public volatile NoteResourceSignal              resourceSignal;\r
88                 public volatile SyncSignal                              syncSignal;\r
89                 public volatile boolean                                 authRefreshNeeded;\r
90                 public volatile boolean                                 syncNeeded;\r
91                 public volatile boolean                                 disableUploads;\r
92                 public volatile boolean                                 syncDeletedContent;\r
93                 private volatile Vector<String>                 dirtyNoteGuids;\r
94                 \r
95             public volatile String username = ""; \r
96             public volatile String password = ""; \r
97                 public volatile String userStoreUrl;\r
98             private final static String consumerKey = "baumgarte"; \r
99             private final static String consumerSecret = "eb8b5740e17cb55f";\r
100             public String noteStoreUrlBase;\r
101             private THttpClient userStoreTrans;\r
102             private TBinaryProtocol userStoreProt;\r
103             private AuthenticationResult authResult;\r
104             private User user; \r
105             private long authTimeRemaining;\r
106             public long authRefreshTime;\r
107             public long failedRefreshes = 0;\r
108             public  THttpClient noteStoreTrans;\r
109             public TBinaryProtocol noteStoreProt;\r
110             public String noteStoreUrl;\r
111             public long sequenceDate;\r
112             public int updateSequenceNumber;\r
113             private boolean refreshNeeded;\r
114             private volatile LinkedBlockingQueue<String> workQueue;\r
115 //              private static int MAX_EMPTY_QUEUE_COUNT = 1;\r
116                 private static int MAX_QUEUED_WAITING = 1000;\r
117                 String dbuid;\r
118                 String dburl;\r
119                 String dbpswd;\r
120                 String dbcpswd;\r
121         \r
122                 \r
123                 \r
124         public SyncRunner(String logname, String u, String uid, String pswd, String cpswd) {\r
125                 logger = new ApplicationLogger(logname);\r
126                 \r
127                 noteSignal = new NoteSignal();\r
128                 status = new StatusSignal();\r
129                 tagSignal = new TagSignal();\r
130                 notebookSignal = new NotebookSignal();\r
131                 noteIndexSignal = new NoteIndexSignal();\r
132                 noteSignal = new NoteSignal();\r
133                 searchSignal = new SavedSearchSignal();\r
134                 syncSignal = new SyncSignal();\r
135                 resourceSignal = new NoteResourceSignal();\r
136                 dbuid = uid;\r
137                 dburl = u;\r
138                 dbpswd = pswd;\r
139                 dbcpswd = cpswd;\r
140 //              this.setAutoDelete(false);\r
141                 \r
142                 isConnected = false;\r
143                 syncNeeded = false;\r
144                 authRefreshNeeded = false;\r
145                 keepRunning = true;\r
146                 idle = true;\r
147                 noteStore = null;\r
148                 userStore = null;\r
149                 authToken = null;\r
150                 disableUploads = false;\r
151 //              setAutoDelete(false);\r
152                 workQueue=new LinkedBlockingQueue<String>(MAX_QUEUED_WAITING);\r
153         }\r
154         @Override\r
155         public void run() {\r
156                 try {\r
157                         logger.log(logger.EXTREME, "Starting thread");\r
158                         conn = new DatabaseConnection(logger, dburl, dbuid, dbpswd, dbcpswd);\r
159                         while(keepRunning) {\r
160                                 String work = workQueue.take();\r
161                                 logger.log(logger.EXTREME, "Work found: " +work);\r
162                                 if (work.equalsIgnoreCase("stop"))\r
163                                         return;\r
164                                 idle=false;\r
165                                 error=false;\r
166                                 if (authRefreshNeeded == true) {\r
167                                         logger.log(logger.EXTREME, "Refreshing connection");\r
168                                         refreshConnection();\r
169                                 }\r
170                                 if (syncNeeded) {\r
171                                         logger.log(logger.EXTREME, "SyncNeeded is true");\r
172                                         refreshNeeded=false;\r
173                                         sequenceDate = conn.getSyncTable().getLastSequenceDate();\r
174                                         updateSequenceNumber = conn.getSyncTable().getUpdateSequenceNumber();\r
175                                         try {\r
176                                                 logger.log(logger.EXTREME, "Beginning sync");\r
177                                                 evernoteSync();\r
178                                                 logger.log(logger.EXTREME, "Sync finished");\r
179                                         } catch (UnknownHostException e) {\r
180                                                 status.message.emit(e.getMessage());\r
181                                         }\r
182                                 }\r
183                                 dirtyNoteGuids = null;\r
184                                 idle=true;\r
185                                 logger.log(logger.EXTREME, "Signaling refresh finished.  refreshNeeded=" +refreshNeeded);\r
186                                 syncSignal.finished.emit(refreshNeeded);\r
187                         }\r
188                 }       \r
189                 catch (InterruptedException e1) {\r
190                         e1.printStackTrace();\r
191                 }\r
192                 conn.dbShutdown();\r
193         }\r
194 \r
195         \r
196         public DatabaseConnection getConnection() {\r
197                 return conn;\r
198         }\r
199 \r
200         public boolean isIdle() {\r
201                 return idle;\r
202         }\r
203 \r
204 \r
205         public void setConnected(boolean c) {\r
206                 isConnected = c;\r
207         }\r
208         public void setKeepRunning(boolean r) {\r
209                 logger.log(logger.EXTREME, "Setting keepRunning=" +r);\r
210                 keepRunning = r;\r
211         }\r
212         public void setNoteStore(NoteStore.Client c) {\r
213                 logger.log(logger.EXTREME, "Setting NoteStore in sync thread");\r
214                 noteStore = c;\r
215         }\r
216         public void setUserStore(UserStore.Client c) {\r
217                 logger.log(logger.EXTREME, "Setting UserStore in sync thread");\r
218                 userStore = c;\r
219         }\r
220 \r
221         public void setEvernoteUpdateCount(long s) {\r
222                 logger.log(logger.EXTREME, "Setting Update Count in sync thread");\r
223                 evernoteUpdateCount = s;\r
224         }\r
225         \r
226         //***************************************************************\r
227     //***************************************************************\r
228     //** These functions deal with Evernote communications\r
229     //***************************************************************\r
230     //***************************************************************\r
231         // Synchronize changes with Evernote\r
232         @SuppressWarnings("unused")\r
233         private void evernoteSync() throws java.net.UnknownHostException {\r
234                 logger.log(logger.HIGH, "Entering SyncRunner.evernoteSync");\r
235 \r
236                 if (isConnected && keepRunning) {\r
237                         error = false;\r
238                         logger.log(logger.EXTREME, "Synchronizing with Evernote");\r
239                         status.message.emit(tr("Synchronizing with Evernote"));\r
240                         \r
241                         // Get user information\r
242                         try {\r
243                                 logger.log(logger.EXTREME, "getting user from userstore");\r
244                                 User user = userStore.getUser(authToken);\r
245                                 logger.log(logger.EXTREME, "Saving user information");\r
246                                 syncSignal.saveUserInformation.emit(user);\r
247                         } catch (EDAMUserException e1) {\r
248                                 e1.printStackTrace();\r
249                                 status.message.emit(tr("User exception getting user account information.  Aborting sync and disconnecting"));\r
250                                 syncSignal.errorDisconnect.emit();\r
251                                 enDisconnect();\r
252                                 return;\r
253                         } catch (EDAMSystemException e1) {\r
254                                 e1.printStackTrace();\r
255                                 status.message.emit(tr("System error user account information.  Aborting sync and disconnecting!"));\r
256                                 syncSignal.errorDisconnect.emit();\r
257                                 enDisconnect();\r
258                                 return;\r
259                         } catch (TException e1) {\r
260                                 e1.printStackTrace();\r
261                                 syncSignal.errorDisconnect.emit();\r
262                                 status.message.emit(tr("Transaction error getting user account information.  Aborting sync and disconnecting!"));\r
263                                 enDisconnect();\r
264                                 return;\r
265                         }\r
266                         \r
267                         // Get sync state\r
268                         SyncState syncState = null;\r
269                         try {   \r
270                                 logger.log(logger.EXTREME, "Getting sync state");\r
271                                 syncState = noteStore.getSyncState(authToken);  \r
272                                 syncSignal.saveUploadAmount.emit(syncState.getUploaded());\r
273                                 syncSignal.saveEvernoteUpdateCount.emit(syncState.getUpdateCount());\r
274                                 evernoteUpdateCount = syncState.getUpdateCount();\r
275                         } catch (EDAMUserException e) {\r
276                                 e.printStackTrace();\r
277                                 status.message.emit(tr("Error getting sync state! Aborting sync and disconnecting!"));\r
278                                 syncSignal.errorDisconnect.emit();\r
279                                 enDisconnect();\r
280                                 return;\r
281                         } catch (EDAMSystemException e) {\r
282                                 e.printStackTrace();\r
283                                 status.message.emit(tr("Error getting sync state! Aborting sync and disconnecting!"));\r
284                                 syncSignal.errorDisconnect.emit();\r
285                                 enDisconnect();\r
286                                 return;\r
287                         } catch (TException e) {\r
288                                 e.printStackTrace();\r
289                                 status.message.emit(tr("Error getting sync state! Aborting sync and disconnecting!"));\r
290                                 syncSignal.errorDisconnect.emit();\r
291                                 enDisconnect();\r
292                                 return;\r
293                         }\r
294                         \r
295                         if (syncState == null) {\r
296                                 logger.log(logger.EXTREME, "Sync State is null");\r
297                                 status.message.emit(tr("Syncronization Error!"));\r
298                                 return;\r
299                         }\r
300 \r
301                         // Determine what to do. \r
302                         // If we need to do a full sync.\r
303                         logger.log(logger.LOW, "Full Sequence Before: " +syncState.getFullSyncBefore());\r
304                         logger.log(logger.LOW, "Last Sequence Date: " +sequenceDate);\r
305                         if (syncState.getFullSyncBefore() > sequenceDate) {\r
306                                 logger.log(logger.EXTREME, "Full sequence date has expired");\r
307                                 sequenceDate = 0;\r
308                                 conn.getSyncTable().setLastSequenceDate(0);\r
309                                 updateSequenceNumber = 0;\r
310                                 conn.getSyncTable().setUpdateSequenceNumber(0);\r
311                         }\r
312                         // Check for "special" sync instructions\r
313                         String syncLinked = conn.getSyncTable().getRecord("FullLinkedNotebookSync");\r
314                         String syncShared = conn.getSyncTable().getRecord("FullLinkedNotebookSync");\r
315                         if (syncLinked != null) {\r
316                                 downloadAllLinkedNotebooks();\r
317                         }\r
318                         if (syncShared != null) {\r
319                                 downloadAllSharedNotebooks();\r
320                         }\r
321                         \r
322                         // If there are remote changes\r
323                         logger.log(logger.LOW, "Update Count: " +syncState.getUpdateCount());\r
324                         logger.log(logger.LOW, "Last Update Count: " +updateSequenceNumber);\r
325                         \r
326                         if (syncState.getUpdateCount() > updateSequenceNumber) {\r
327                                 logger.log(logger.EXTREME, "Refresh needed is true");\r
328                                 refreshNeeded = true;\r
329                                 logger.log(logger.EXTREME, "Downloading changes");\r
330                                 syncRemoteToLocal();\r
331                         }\r
332                         \r
333                         if (!disableUploads) {\r
334                                 logger.log(logger.EXTREME, "Uploading changes");\r
335                                 // Synchronize remote changes\r
336                                 if (!error)\r
337                                         syncExpunged();\r
338                                 if (!error)\r
339                                         syncLocalTags();\r
340                                 if (!error)\r
341                                         syncLocalNotebooks();\r
342                                 if (!error) \r
343                                         syncDeletedNotes();\r
344                                 if (!error)\r
345                                         syncLocalNotes();\r
346                                 if (!error)\r
347                                         syncLocalSavedSearches();\r
348                         }\r
349                         if (refreshNeeded)\r
350                                 syncSignal.refreshLists.emit();\r
351                         if (!error) {\r
352                                 logger.log(logger.EXTREME, "Sync completed.  Errors=" +error);\r
353                                 if (!disableUploads) \r
354                                         status.message.emit(tr("Synchronizing complete"));\r
355                                 else\r
356                                         status.message.emit(tr("Download syncronization complete.  Uploads have been disabled."));\r
357                                 \r
358                                 logger.log(logger.EXTREME, "Saving sync time");\r
359                                 if (syncState.getCurrentTime() > sequenceDate)\r
360                                         sequenceDate = syncState.getCurrentTime();\r
361                                 if (syncState.getUpdateCount() > updateSequenceNumber)\r
362                                         updateSequenceNumber = syncState.getUpdateCount();\r
363                                 conn.getSyncTable().setLastSequenceDate(sequenceDate);\r
364                                 conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
365                         }\r
366                 }\r
367                 logger.log(logger.HIGH, "Leaving SyncRunner.evernoteSync");\r
368         }\r
369         // Sync deleted items with Evernote\r
370         private void syncExpunged() {\r
371                 logger.log(logger.HIGH, "Entering SyncRunner.syncExpunged");\r
372                 \r
373                 List<DeletedItemRecord> expunged = conn.getDeletedTable().getAllDeleted();\r
374                 boolean error = false;\r
375                 for (int i=0; i<expunged.size() && keepRunning; i++) {\r
376                         \r
377                         if (authRefreshNeeded)\r
378                                 refreshConnection();\r
379 \r
380                         try {\r
381                                 if (expunged.get(i).type.equalsIgnoreCase("TAG")) {\r
382                                         logger.log(logger.EXTREME, "Tag expunged");\r
383                                         updateSequenceNumber = noteStore.expungeTag(authToken, expunged.get(i).guid);\r
384                                         conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
385                                         \r
386                                 }\r
387                                 if      (expunged.get(i).type.equalsIgnoreCase("NOTEBOOK")) {\r
388                                         logger.log(logger.EXTREME, "Notebook expunged");\r
389                                         updateSequenceNumber = noteStore.expungeNotebook(authToken, expunged.get(i).guid);\r
390                                         conn.getSyncTable().setLastSequenceDate(sequenceDate);\r
391                                 }\r
392                                 if (expunged.get(i).type.equalsIgnoreCase("NOTE")) {\r
393                                         logger.log(logger.EXTREME, "Note expunged");\r
394                                         updateSequenceNumber = noteStore.deleteNote(authToken, expunged.get(i).guid);\r
395                                         conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
396                                 }\r
397                                 if (expunged.get(i).type.equalsIgnoreCase("SAVEDSEARCH")) {\r
398                                         logger.log(logger.EXTREME, "saved search expunged");\r
399                                         updateSequenceNumber = noteStore.expungeSearch(authToken, expunged.get(i).guid);\r
400                                         conn.getSyncTable().setLastSequenceDate(sequenceDate);\r
401                                 }\r
402                         } catch (EDAMUserException e) {\r
403                                 logger.log(logger.LOW, "EDAM User Excepton in syncExpunged: " +expunged.get(i).guid);\r
404                                 logger.log(logger.LOW, e.getStackTrace());\r
405                                 error = true;\r
406                         } catch (EDAMSystemException e) {\r
407                                 logger.log(logger.LOW, "EDAM System Excepton in syncExpunged: "+expunged.get(i).guid);\r
408                                 logger.log(logger.LOW, e.getStackTrace());\r
409                                 error=true;\r
410                         } catch (EDAMNotFoundException e) {\r
411                                 logger.log(logger.LOW, "EDAM Not Found Excepton in syncExpunged: "+expunged.get(i).guid);\r
412 //                              logger.log(logger.LOW, e.getStackTrace());\r
413                                 //error=true;\r
414                         } catch (TException e) {\r
415                                 logger.log(logger.LOW, "EDAM TExcepton in syncExpunged: "+expunged.get(i).guid);\r
416                                 logger.log(logger.LOW, e.getStackTrace());\r
417                                 error=true;\r
418                         }\r
419                 }\r
420                 if (!error)\r
421                         conn.getDeletedTable().expungeAllDeletedRecords();\r
422                 \r
423                 logger.log(logger.HIGH, "Leaving SyncRunner.syncExpunged");\r
424 \r
425         }\r
426         private void syncDeletedNotes() {\r
427                 if (syncDeletedContent)\r
428                         return;\r
429                 logger.log(logger.HIGH, "Entering SyncRunner.syncDeletedNotes");\r
430                 status.message.emit(tr("Synchronizing deleted notes."));\r
431 \r
432                 List<Note> notes = conn.getNoteTable().getDirty();\r
433                 // Sync the local notebooks with Evernote's\r
434                 for (int i=0; i<notes.size() && keepRunning; i++) {\r
435                         \r
436                         if (authRefreshNeeded)\r
437                                 refreshConnection();\r
438                         \r
439                         Note enNote = notes.get(i);\r
440                         try {\r
441                                 if (enNote.getUpdateSequenceNum() > 0 && (enNote.isActive() == false || enNote.getDeleted() > 0)) {\r
442                                         if (syncDeletedContent) {\r
443                                                 logger.log(logger.EXTREME, "Deleted note found & synch content selected");\r
444                                                 Note delNote = conn.getNoteTable().getNote(enNote.getGuid(), true, true, true, true, true);\r
445                                                 delNote = getNoteContent(delNote);\r
446                                                 delNote = noteStore.updateNote(authToken, delNote);\r
447                                                 enNote.setUpdateSequenceNum(delNote.getUpdateSequenceNum());\r
448                                                 conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum());\r
449                                         } else {\r
450                                                 logger.log(logger.EXTREME, "Deleted note found & sync content not selected");\r
451                                                 int usn = noteStore.deleteNote(authToken, enNote.getGuid());\r
452                                                 enNote.setUpdateSequenceNum(usn);\r
453                                                 conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum());                                                \r
454                                         }\r
455                                         logger.log(logger.EXTREME, "Resetting deleted dirty flag");\r
456                                         conn.getNoteTable().resetDirtyFlag(enNote.getGuid());\r
457                                         updateSequenceNumber = enNote.getUpdateSequenceNum();\r
458                                         logger.log(logger.EXTREME, "Saving sequence number");\r
459                                         conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
460                                 }                               \r
461                         } catch (EDAMUserException e) {\r
462                                 //logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotes "+e);\r
463                                 //status.message.emit("Error sending local note: " +e.getParameter());\r
464                                 //logger.log(logger.LOW, e.toString()); \r
465                                 //error = true;\r
466                         } catch (EDAMSystemException e) {\r
467                                 logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotes "+e);\r
468                                 status.message.emit(tr("Error: ") +e);\r
469                                 logger.log(logger.LOW, e.toString());           \r
470                                 error = true;\r
471                         } catch (EDAMNotFoundException e) {\r
472                                 //logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalNotes " +e);\r
473                                 //status.message.emit("Error deleting local note: " +e +" - Continuing");\r
474                                 //logger.log(logger.LOW, e.toString());         \r
475                                 //error = true;\r
476                         } catch (TException e) {\r
477                                 logger.log(logger.LOW, "*** EDAM TExcepton syncLocalNotes "+e);\r
478                                 status.message.emit(tr("Error sending local note: ") +e);\r
479                                 logger.log(logger.LOW, e.toString());   \r
480                                 error = true;\r
481                         }               \r
482                 }\r
483         }\r
484         // Sync notes with Evernote\r
485         private void syncLocalNotes() {\r
486                 logger.log(logger.HIGH, "Entering SyncRunner.syncNotes");\r
487                 status.message.emit(tr("Sending local notes."));\r
488 \r
489                 List<Note> notes = conn.getNoteTable().getDirty();\r
490                 // Sync the local notebooks with Evernote's\r
491                 for (int i=0; i<notes.size() && keepRunning; i++) {\r
492                         \r
493                         if (authRefreshNeeded)\r
494                                 refreshConnection();\r
495                         \r
496                         Note enNote = notes.get(i);\r
497                         if (enNote.isActive()) {\r
498                                 try {\r
499                                         logger.log(logger.EXTREME, "Active dirty note found - non new");\r
500                                         if (enNote.getUpdateSequenceNum() > 0) {\r
501                                                 enNote = getNoteContent(enNote);\r
502                                                 logger.log(logger.MEDIUM, "Updating note : "+ enNote.getGuid() +" <title>" +enNote.getTitle()+"</title>");\r
503                                                 enNote = noteStore.updateNote(authToken, enNote);\r
504                                         } else { \r
505                                                 logger.log(logger.EXTREME, "Active dirty found - new note");\r
506                                                 logger.log(logger.MEDIUM, "Creating note : "+ enNote.getGuid() +" <title>" +enNote.getTitle()+"</title>");\r
507                                                 String oldGuid = enNote.getGuid();\r
508                                                 enNote = getNoteContent(enNote);\r
509                                                 enNote = noteStore.createNote(authToken, enNote);\r
510                                                 noteSignal.guidChanged.emit(oldGuid, enNote.getGuid());\r
511                                                 conn.getNoteTable().updateNoteGuid(oldGuid, enNote.getGuid());\r
512                                         }\r
513                                         updateSequenceNumber = enNote.getUpdateSequenceNum();\r
514                                         logger.log(logger.EXTREME, "Saving note");\r
515                                         conn.getNoteTable().updateNoteSequence(enNote.getGuid(), enNote.getUpdateSequenceNum());\r
516                                         List<Resource> rl = enNote.getResources();\r
517                                         logger.log(logger.EXTREME, "Getting note resources");\r
518                                         for (int j=0; j<enNote.getResourcesSize() && keepRunning; j++) {\r
519                                                 Resource newRes = rl.get(j);\r
520                                                 Data d = newRes.getData();\r
521                                                 if (d!=null) {  \r
522                                                         logger.log(logger.EXTREME, "Calculating resource hash");\r
523                                                         String hash = byteArrayToHexString(d.getBodyHash());\r
524                                                         logger.log(logger.EXTREME, "updating resources by hash");\r
525                                                         String oldGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(enNote.getGuid(), hash);\r
526                                                         conn.getNoteTable().updateNoteResourceGuidbyHash(enNote.getGuid(), newRes.getGuid(), hash);\r
527                                                         resourceSignal.resourceGuidChanged.emit(enNote.getGuid(), oldGuid, newRes.getGuid());\r
528                                                 }\r
529                                         }\r
530                                         logger.log(logger.EXTREME, "Resetting note dirty flag");\r
531                                         conn.getNoteTable().resetDirtyFlag(enNote.getGuid());\r
532                                         updateSequenceNumber = enNote.getUpdateSequenceNum();\r
533                                         logger.log(logger.EXTREME, "Emitting note sequence number change");\r
534                                         conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
535 \r
536                                 } catch (EDAMUserException e) {\r
537                                         logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotes "+e);\r
538                                         status.message.emit(tr("Error sending local note: ")     +e.getParameter());\r
539                                         logger.log(logger.LOW, e.toString());   \r
540                                         error = true;\r
541                                 } catch (EDAMSystemException e) {\r
542                                         logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotes "+e);\r
543                                         status.message.emit(tr("Error: ") +e);\r
544                                         logger.log(logger.LOW, e.toString());           \r
545                                         error = true;\r
546                                 } catch (EDAMNotFoundException e) {\r
547                                         logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalNotes " +e);\r
548                                         status.message.emit(tr("Error sending local note: ") +e);\r
549                                         logger.log(logger.LOW, e.toString());   \r
550                                         error = true;\r
551                                 } catch (TException e) {\r
552                                         logger.log(logger.LOW, "*** EDAM TExcepton syncLocalNotes "+e);\r
553                                         status.message.emit(tr("Error sending local note: ") +e);\r
554                                         logger.log(logger.LOW, e.toString());   \r
555                                         error = true;\r
556                                 }\r
557                         }\r
558                 }\r
559                 logger.log(logger.HIGH, "Entering SyncRunner.syncNotes");\r
560 \r
561         }\r
562         // Sync Notebooks with Evernote\r
563         private void syncLocalNotebooks() {\r
564                 logger.log(logger.HIGH, "Entering SyncRunner.syncLocalNotebooks");\r
565                 \r
566                 status.message.emit(tr("Sending local notebooks."));\r
567                 List<Notebook> remoteList = new ArrayList<Notebook>();\r
568                 try {\r
569                         logger.log(logger.EXTREME, "Getting remote notebooks to compare with local");\r
570                         remoteList = noteStore.listNotebooks(authToken);\r
571                 } catch (EDAMUserException e1) {\r
572                         logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotebooks getting remote Notebook List");\r
573                         status.message.emit(tr("Error: ") +e1);\r
574                         logger.log(logger.LOW, e1.toString());          \r
575                         error = true;\r
576                 } catch (EDAMSystemException e1) {\r
577                         logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotebooks getting remote Notebook List");\r
578                         status.message.emit(tr("Error: ") +e1);\r
579                         logger.log(logger.LOW, e1.toString());  \r
580                         error = true;\r
581                 } catch (TException e1) {\r
582                         logger.log(logger.LOW, "*** EDAM Transaction Excepton syncLocalNotebooks getting remote Notebook List");\r
583                         status.message.emit(tr("Error: ") +e1);\r
584                         logger.log(logger.LOW, e1.toString());  \r
585                         error = true;\r
586                 }\r
587                 logger.log(logger.EXTREME, "Getting local dirty notebooks");\r
588                 List<Notebook> notebooks = conn.getNotebookTable().getDirty();\r
589                 int sequence;\r
590                 // Sync the local notebooks with Evernote's\r
591                 for (int i=0; i<notebooks.size() && keepRunning; i++) {\r
592                         \r
593                         if (authRefreshNeeded)\r
594                                 refreshConnection();\r
595                         \r
596                         Notebook enNotebook = notebooks.get(i);\r
597                         try {\r
598                                 if (enNotebook.getUpdateSequenceNum() > 0) {\r
599                                         logger.log(logger.EXTREME, "Existing notebook is dirty");\r
600                                         sequence = noteStore.updateNotebook(authToken, enNotebook);\r
601                                 } else {\r
602                                         logger.log(logger.EXTREME, "New dirty notebook found");\r
603                                         String oldGuid = enNotebook.getGuid();\r
604                                         boolean found = false;\r
605                                         \r
606                                         // Look for a notebook with the same name.  If one is found, we don't need \r
607                                         // to create another one\r
608                                         logger.log(logger.EXTREME, "Looking for matching notebook name");\r
609                                         for (int k=0; k<remoteList.size() && !found && keepRunning; k++) {\r
610                                                 if (remoteList.get(k).getName().equalsIgnoreCase(enNotebook.getName())) {\r
611                                                         enNotebook = remoteList.get(k);\r
612                                                         logger.log(logger.EXTREME, "Matching notebook found");\r
613                                                         found = true;\r
614                                                 }\r
615                                         }\r
616                                         if (!found)\r
617                                                 enNotebook = noteStore.createNotebook(authToken, enNotebook);\r
618                                         \r
619                                         logger.log(logger.EXTREME, "Updating notebook in database");\r
620                                         conn.getNotebookTable().updateNotebookGuid(oldGuid, enNotebook.getGuid());\r
621                                         sequence = enNotebook.getUpdateSequenceNum();\r
622                                 }\r
623                                 logger.log(logger.EXTREME, "Updating notebook sequence in database");\r
624                                 conn.getNotebookTable().updateNotebookSequence(enNotebook.getGuid(), sequence);\r
625                                 logger.log(logger.EXTREME, "Resetting dirty flag in notebook");\r
626                                 conn.getNotebookTable().resetDirtyFlag(enNotebook.getGuid());\r
627                                 updateSequenceNumber = sequence;\r
628                                 logger.log(logger.EXTREME, "Emitting sequence number to main thread");\r
629                                 conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
630                         } catch (EDAMUserException e) {\r
631                                 logger.log(logger.LOW, "*** EDAM User Excepton syncLocalNotebooks");\r
632                                 logger.log(logger.LOW, e.toString());   \r
633                                 error = true;\r
634                         } catch (EDAMSystemException e) {\r
635                                 logger.log(logger.LOW, "*** EDAM System Excepton syncLocalNotebooks");\r
636                                 logger.log(logger.LOW, e.toString());           \r
637                                 error = true;\r
638                         } catch (EDAMNotFoundException e) {\r
639                                 logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalNotebooks");\r
640                                 logger.log(logger.LOW, e.toString());           \r
641                                 error = true;\r
642                         } catch (TException e) {\r
643                                 logger.log(logger.LOW, "*** EDAM TExcepton syncLocalNotebooks");\r
644                                 logger.log(logger.LOW, e.toString());   \r
645                                 error = true;\r
646                         }               \r
647                 }\r
648                 logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalNotebooks");\r
649 \r
650         }\r
651         // Sync Tags with Evernote\r
652         private void syncLocalTags() {\r
653                 logger.log(logger.HIGH, "Entering SyncRunner.syncLocalTags");\r
654                 List<Tag> remoteList = new ArrayList<Tag>();\r
655                 status.message.emit(tr("Sending local tags."));\r
656                 \r
657                 try {\r
658                         logger.log(logger.EXTREME, "Getting remote tags to compare names with the local tags");\r
659                         remoteList = noteStore.listTags(authToken);\r
660                 } catch (EDAMUserException e1) {\r
661                         logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags getting remote Tag List");\r
662                         status.message.emit(tr("Error: ") +e1);\r
663                         logger.log(logger.LOW, e1.toString());  \r
664                         error = true;\r
665                 } catch (EDAMSystemException e1) {\r
666                         logger.log(logger.LOW, "*** EDAM System Excepton syncLocalTags getting remote Tag List");\r
667                         status.message.emit(tr("Error: ") +e1);\r
668                         logger.log(logger.LOW, e1.toString());          \r
669                         error = true;\r
670                 } catch (TException e1) {\r
671                         logger.log(logger.LOW, "*** EDAM Transaction Excepton syncLocalTags getting remote Tag List");\r
672                         status.message.emit(tr("Error: ") +e1);\r
673                         logger.log(logger.LOW, e1.toString());  \r
674                         error = true;\r
675                 }               \r
676                 \r
677                 int sequence;\r
678                 \r
679                 Tag enTag = findNextTag();\r
680                 while(enTag!=null) {\r
681                         if (authRefreshNeeded)\r
682                                 refreshConnection();\r
683 \r
684                         try {\r
685                                 if (enTag.getUpdateSequenceNum() > 0) {\r
686                                         logger.log(logger.EXTREME, "Updating tag");\r
687                                         sequence = noteStore.updateTag(authToken, enTag);\r
688                                 } else {\r
689                                         \r
690                                         // Look for a tag with the same name.  If one is found, we don't need \r
691                                         // to create another one\r
692                                         logger.log(logger.EXTREME, "New tag.  Comparing with remote names");\r
693                                         boolean found = false;\r
694                                         String oldGuid = enTag.getGuid();\r
695                                         for (int k=0; k<remoteList.size() && !found && keepRunning; k++) {\r
696                                                 if (remoteList.get(k).getName().equalsIgnoreCase(enTag.getName())) {\r
697                                                         conn.getTagTable().updateTagGuid(enTag.getGuid(), remoteList.get(k).getGuid());\r
698                                                         enTag = remoteList.get(k);\r
699                                                         logger.log(logger.EXTREME, "Matching tag name found");\r
700                                                         found = true;\r
701                                                 }\r
702                                         }\r
703                                         if (!found)\r
704                                                 enTag = noteStore.createTag(authToken, enTag);\r
705                                         else\r
706                                                 enTag.setUpdateSequenceNum(noteStore.updateTag(authToken,enTag));\r
707                                         sequence = enTag.getUpdateSequenceNum();\r
708                                         if (!oldGuid.equals(enTag.getGuid())) {\r
709                                                 logger.log(logger.EXTREME, "Updating tag guid");\r
710                                                 conn.getTagTable().updateTagGuid(oldGuid, enTag.getGuid());\r
711                                         }\r
712                                 }\r
713                                 logger.log(logger.EXTREME, "Updating tag sequence number");\r
714                                 conn.getTagTable().updateTagSequence(enTag.getGuid(), sequence);\r
715                                 logger.log(logger.EXTREME, "Resetting tag dirty flag");\r
716                                 conn.getTagTable().resetDirtyFlag(enTag.getGuid());\r
717                                 logger.log(logger.EXTREME, "Emitting sequence number to the main thread.");\r
718                                 updateSequenceNumber = sequence;\r
719                                 conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
720                         } catch (EDAMUserException e) {\r
721                                 logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags");\r
722                                 logger.log(logger.LOW, e.toString());           \r
723                                 error = true;\r
724                         } catch (EDAMSystemException e) {\r
725                                 logger.log(logger.LOW, "** EDAM System Excepton syncLocalTags");\r
726                                 logger.log(logger.LOW, e.toString());   \r
727                                 error = true;\r
728                         } catch (EDAMNotFoundException e) {\r
729                                 logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalTags");\r
730                                 logger.log(logger.LOW, e.toString());   \r
731                                 error = true;\r
732                         } catch (TException e) {\r
733                                 logger.log(logger.LOW, "*** EDAM TExcepton syncLocalTags");\r
734                                 logger.log(logger.LOW, e.toString());           \r
735                                 error = true;\r
736                         }       \r
737                         \r
738                         // Find the next tag\r
739                         logger.log(logger.EXTREME, "Finding next tag");\r
740                         enTag = findNextTag();\r
741                 }\r
742                 logger.log(logger.HIGH, "Leaving SyncRunner.syncLocalTags");\r
743         }\r
744         // Sync Tags with Evernote\r
745         private void syncLocalSavedSearches() {\r
746                 logger.log(logger.HIGH, "Entering SyncRunner.syncLocalSavedSearches");\r
747                 List<SavedSearch> remoteList = new ArrayList<SavedSearch>();\r
748                 status.message.emit(tr("Sending saved searches."));\r
749         \r
750                 logger.log(logger.EXTREME, "Getting saved searches to compare with local");\r
751                 try {\r
752                         remoteList = noteStore.listSearches(authToken);\r
753                 } catch (EDAMUserException e1) {\r
754                         logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags getting remote saved search List");\r
755                         status.message.emit(tr("Error: ") +e1);\r
756                         logger.log(logger.LOW, e1.toString());  \r
757                         error = true;\r
758                 } catch (EDAMSystemException e1) {\r
759                         logger.log(logger.LOW, "*** EDAM System Excepton syncLocalTags getting remote saved search List");\r
760                         status.message.emit(tr("Error: ") +e1);\r
761                         logger.log(logger.LOW, e1.toString());          \r
762                         error = true;\r
763                 } catch (TException e1) {\r
764                         logger.log(logger.LOW, "*** EDAM Transaction Excepton syncLocalTags getting remote saved search List");\r
765                         status.message.emit(tr("Error: ") +e1);\r
766                         logger.log(logger.LOW, e1.toString());  \r
767                         error = true;\r
768                 }               \r
769                 \r
770                 List<SavedSearch> searches = conn.getSavedSearchTable().getDirty();\r
771                 int sequence;\r
772                 // Sync the local notebooks with Evernote's\r
773                 logger.log(logger.EXTREME, "Beginning to send saved searches");\r
774                 for (int i=0; i<searches.size() &&  keepRunning; i++) {\r
775                         \r
776                         if (authRefreshNeeded)\r
777                                 refreshConnection();\r
778                         \r
779                         SavedSearch enSearch = searches.get(i);\r
780                         try {\r
781                                 if (enSearch.getUpdateSequenceNum() > 0) \r
782                                         sequence = noteStore.updateSearch(authToken, enSearch);\r
783                                 else {\r
784                                         logger.log(logger.EXTREME, "New saved search found.");\r
785                                         // Look for a tag with the same name.  If one is found, we don't need \r
786                                         // to create another one\r
787                                         boolean found = false;\r
788                                         logger.log(logger.EXTREME, "Matching remote saved search names with local");\r
789                                         for (int k=0; k<remoteList.size() && !found && keepRunning; k++) {\r
790                                                 if (remoteList.get(k).getName().equalsIgnoreCase(enSearch.getName())) {\r
791                                                         enSearch = remoteList.get(k);\r
792                                                         found = true;\r
793                                                         logger.log(logger.EXTREME, "Matching saved search found");\r
794                                                         sequence = enSearch.getUpdateSequenceNum();\r
795                                                 }\r
796                                         }\r
797 \r
798                                         String oldGuid = enSearch.getGuid();\r
799                                         if (!found)\r
800                                                 enSearch = noteStore.createSearch(authToken, enSearch);\r
801                                         sequence = enSearch.getUpdateSequenceNum();\r
802                                         logger.log(logger.EXTREME, "Updating tag guid in local database");\r
803                                         conn.getTagTable().updateTagGuid(oldGuid, enSearch.getGuid());\r
804                                 }\r
805                                 logger.log(logger.EXTREME, "Updating tag sequence in local database");\r
806                                 conn.getSavedSearchTable().updateSavedSearchSequence(enSearch.getGuid(), sequence);\r
807                                 logger.log(logger.EXTREME, "Resetting tag dirty flag");\r
808                                 conn.getSavedSearchTable().resetDirtyFlag(enSearch.getGuid());\r
809                                 logger.log(logger.EXTREME, "Emitting sequence number to the main thread.");\r
810                                 updateSequenceNumber = sequence;\r
811                                 conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
812                         } catch (EDAMUserException e) {\r
813                                 logger.log(logger.LOW, "*** EDAM User Excepton syncLocalTags");\r
814                                 logger.log(logger.LOW, e.toString());   \r
815                                 error = true;\r
816                         } catch (EDAMSystemException e) {\r
817                                 logger.log(logger.LOW, "** EDAM System Excepton syncLocalTags");\r
818                                 logger.log(logger.LOW, e.toString());   \r
819                                 error = true;\r
820                         } catch (EDAMNotFoundException e) {\r
821                                 logger.log(logger.LOW, "*** EDAM Not Found Excepton syncLocalTags");\r
822                                 logger.log(logger.LOW, e.toString());   \r
823                                 error = true;\r
824                         } catch (TException e) {\r
825                                 logger.log(logger.LOW, "*** EDAM TExcepton syncLocalTags");\r
826                                 logger.log(logger.LOW, e.toString());   \r
827                                 error = true;\r
828                         }               \r
829                 }\r
830                 logger.log(logger.HIGH, "Entering SyncRunner.syncLocalSavedSearches");\r
831         }       \r
832 \r
833         // Sync evernote changes with local database\r
834         private void syncRemoteToLocal() {\r
835                 logger.log(logger.HIGH, "Entering SyncRunner.syncRemoteToLocal");\r
836 \r
837                 List<Note> dirtyNotes = conn.getNoteTable().getDirty();\r
838                 dirtyNoteGuids = new Vector<String>();\r
839                 for (int i=0; i<dirtyNotes.size() && keepRunning; i++) {\r
840                         dirtyNoteGuids.add(dirtyNotes.get(i).getGuid());\r
841                 }\r
842                 \r
843                 int chunkSize = 10;\r
844                 SyncChunk chunk = null;\r
845                 boolean fullSync = false;\r
846                 boolean more = true;\r
847                 \r
848                 if (updateSequenceNumber == 0)\r
849                         fullSync = true;\r
850                 \r
851                 status.message.emit(tr("Downloading 0% complete."));\r
852                 \r
853                 while(more &&  keepRunning) {\r
854                         \r
855                         if (authRefreshNeeded)\r
856                                 refreshConnection();\r
857                         \r
858                         chunk = null;\r
859                         int sequence = updateSequenceNumber;\r
860                         try {\r
861                                 logger.log(logger.EXTREME, "Getting chunk from Evernote");\r
862                                 chunk = noteStore.getSyncChunk(authToken, sequence, chunkSize, fullSync);\r
863                         } catch (EDAMUserException e) {\r
864                                 error = true;\r
865                                 e.printStackTrace();\r
866                                 status.message.emit(e.getMessage());\r
867                         } catch (EDAMSystemException e) {\r
868                                 error = true;\r
869                                 e.printStackTrace();\r
870                                 status.message.emit(e.getMessage());\r
871                         } catch (TException e) {\r
872                                 error = true;\r
873                                 e.printStackTrace();\r
874                                 status.message.emit(e.getMessage());\r
875                         } \r
876                         if (error || chunk == null) \r
877                                 return;\r
878                                 \r
879                 \r
880                         \r
881                         syncRemoteTags(chunk.getTags());\r
882                         syncRemoteSavedSearches(chunk.getSearches());\r
883                         syncRemoteNotebooks(chunk.getNotebooks());\r
884                         syncRemoteNotes(chunk.getNotes(), fullSync);\r
885                         syncRemoteResources(chunk.getResources());\r
886                         syncRemoteLinkedNotebooks(chunk.getLinkedNotebooks());\r
887                         \r
888                         // Do the local deletes\r
889                         logger.log(logger.EXTREME, "Doing local deletes");\r
890                         List<String> guid = chunk.getExpungedNotes();\r
891                         if (guid != null) {\r
892                                 for (int i=0; i<guid.size() && keepRunning; i++) {\r
893                                         String notebookGuid = "";\r
894                                         Note localNote = conn.getNoteTable().getNote(guid.get(i), false, false, false, false, false);\r
895                                         if (localNote != null) {\r
896                                                 conn.getNoteTable().updateNoteSequence(guid.get(i), 0);\r
897                                                 notebookGuid = localNote.getNotebookGuid();\r
898                                         }\r
899                                         if (!conn.getNotebookTable().isNotebookLocal(notebookGuid)) {\r
900                                                 logger.log(logger.EXTREME, "Expunging local note from database");\r
901                                                 conn.getNoteTable().expungeNote(guid.get(i), true, false);\r
902                                         }\r
903                                 }\r
904                         }\r
905                         guid = chunk.getExpungedNotebooks();\r
906                         if (guid != null)\r
907                                 for (int i=0; i<guid.size() && keepRunning; i++) {\r
908                                         logger.log(logger.EXTREME, "Expunging local notebook from database");\r
909                                         conn.getNotebookTable().expungeNotebook(guid.get(i), false);\r
910                                 }\r
911                         guid = chunk.getExpungedTags();\r
912                         if (guid != null)\r
913                                 for (int i=0; i<guid.size() && keepRunning; i++) {\r
914                                         logger.log(logger.EXTREME, "Expunging tags from local database");\r
915                                         conn.getTagTable().expungeTag(guid.get(i), false);\r
916                                 }\r
917                         guid = chunk.getExpungedSearches();\r
918                         if (guid != null) \r
919                                 for (int i=0; i<guid.size() && keepRunning; i++) {\r
920                                         logger.log(logger.EXTREME, "Expunging saved search from local database");\r
921                                         conn.getSavedSearchTable().expungeSavedSearch(guid.get(i), false);\r
922                                 }\r
923                         guid = chunk.getExpungedLinkedNotebooks();\r
924                         if (guid != null) \r
925                                 for (int i=0; i<guid.size() && keepRunning; i++) {\r
926                                         logger.log(logger.EXTREME, "Expunging linked notebook from local database");\r
927                                         conn.getLinkedNotebookTable().expungeNotebook(guid.get(i), false);\r
928                                 }\r
929 \r
930                         \r
931                         // Check for more notes\r
932                         if (chunk.getChunkHighUSN() <= updateSequenceNumber) \r
933                                 more = false;\r
934                         if (error)\r
935                                 more = false;\r
936                         logger.log(logger.EXTREME, "More notes? " +more);\r
937 \r
938                         \r
939                         // Save the chunk sequence number\r
940                         if (!error && chunk.getChunkHighUSN() > 0) {\r
941                                 logger.log(logger.EXTREME, "emitting sequence number to main thread");\r
942                                 updateSequenceNumber = chunk.getChunkHighUSN();\r
943                                 conn.getSyncTable().setLastSequenceDate(chunk.getCurrentTime());\r
944                                 conn.getSyncTable().setUpdateSequenceNumber(updateSequenceNumber);\r
945                         }\r
946                         \r
947                         \r
948                         if (more) {\r
949                                 long pct = chunk.getChunkHighUSN() * 100;\r
950                                 conn.getSyncTable().setLastSequenceDate(chunk.getCurrentTime());\r
951                                 pct = pct/evernoteUpdateCount;\r
952                                 status.message.emit(tr("Downloading ") +new Long(pct).toString()+tr("% complete."));\r
953                         }\r
954                 }\r
955 \r
956                 logger.log(logger.HIGH, "Leaving SyncRunner.syncRemoteToLocal");\r
957         }\r
958         // Sync remote tags\r
959         private void syncRemoteTags(List<Tag> tags) {\r
960                 logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteTags");\r
961                 if (tags != null) {\r
962                         for (int i=0; i<tags.size() && keepRunning; i++) {\r
963                                 String oldGuid;\r
964                                 oldGuid = conn.getTagTable().findTagByName(tags.get(i).getName());\r
965                                 if (oldGuid != null && !tags.get(i).getGuid().equalsIgnoreCase(oldGuid))\r
966                                         conn.getTagTable().updateTagGuid(oldGuid, tags.get(i).getGuid());\r
967                                 conn.getTagTable().syncTag(tags.get(i), false);\r
968                         }\r
969                 }\r
970                 logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteTags");\r
971         }\r
972         // Sync remote saved searches\r
973         private void syncRemoteSavedSearches(List<SavedSearch> searches) {\r
974                 logger.log(logger.EXTREME, "Entering SyncRunner.syncSavedSearches");\r
975                 if (searches != null) {\r
976                         for (int i=0; i<searches.size() && keepRunning; i++) {\r
977                                 String oldGuid;\r
978                                 oldGuid = conn.getSavedSearchTable().findSavedSearchByName(searches.get(i).getName());\r
979                                 if (oldGuid != null && !searches.get(i).getGuid().equalsIgnoreCase(oldGuid))\r
980                                         conn.getSavedSearchTable().updateSavedSearchGuid(oldGuid, searches.get(i).getGuid());\r
981                                 conn.getSavedSearchTable().syncSavedSearch(searches.get(i), false);\r
982                         }\r
983                 }\r
984                 logger.log(logger.EXTREME, "Leaving SyncRunner.syncSavedSearches");\r
985         }\r
986         // Sync remote linked notebooks\r
987         private void syncRemoteLinkedNotebooks(List<LinkedNotebook> books) {\r
988                 logger.log(logger.EXTREME, "Entering SyncRunner.syncSavedSearches");\r
989                 if (books != null) {\r
990                         for (int i=0; i<books.size() && keepRunning; i++) {\r
991                                 conn.getLinkedNotebookTable().updateNotebook(books.get(i), false); \r
992                         }\r
993                 }\r
994                 logger.log(logger.EXTREME, "Leaving SyncRunner.syncSavedSearches");\r
995         }\r
996         // Sync remote Notebooks 2\r
997         private void syncRemoteNotebooks(List<Notebook> notebooks) {\r
998                 logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotebooks");\r
999                 if (notebooks != null) {\r
1000                         for (int i=0; i<notebooks.size() && keepRunning; i++) {\r
1001                                 String oldGuid;\r
1002                                 oldGuid = conn.getNotebookTable().findNotebookByName(notebooks.get(i).getName());\r
1003                                 if (oldGuid != null && !conn.getNotebookTable().isNotebookLocal(oldGuid) && !notebooks.get(i).getGuid().equalsIgnoreCase(oldGuid))\r
1004                                         conn.getNotebookTable().updateNotebookGuid(oldGuid, notebooks.get(i).getGuid());\r
1005                                 conn.getNotebookTable().syncNotebook(notebooks.get(i), false); \r
1006                         }\r
1007                 }                       \r
1008                 logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteNotebooks");\r
1009         }\r
1010         // Sync remote Resources\r
1011         private void syncRemoteResources(List<Resource> resource) {\r
1012                 // This is how the logic for this works.\r
1013                 // 1.) If the resource is not in the local database, we add it.\r
1014                 // 2.) If a copy of the resource is in the local database and the note isn't dirty, we update the local copy\r
1015                 // 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
1016                 //     is a conflict.  The note conflict should get a copy of the resource at that time.\r
1017                 \r
1018                 logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteResources");\r
1019                 if (resource != null) {\r
1020                         for (int i=0; i<resource.size() && keepRunning; i++) {\r
1021                                 boolean saveNeeded = false;\r
1022 /* #1 */                Resource r = getEvernoteResource(resource.get(i).getGuid(), true,true,true);\r
1023                                 Resource l = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), false);\r
1024                                 if (l == null) {\r
1025                                         saveNeeded = true;\r
1026                                 } else {\r
1027 /* #2 */                        boolean isNoteDirty = conn.getNoteTable().isNoteDirty(r.getNoteGuid());\r
1028                                         if (!isNoteDirty)\r
1029                                                 saveNeeded = true;\r
1030                                         else {\r
1031 /* #3 */                                String remoteHash = "";\r
1032                                                 if (r != null && r.getData() != null && r.getData().getBodyHash() != null)\r
1033                                                         remoteHash = byteArrayToHexString(r.getData().getBodyHash());\r
1034                                                 String localHash = "";\r
1035                                                 if (l != null && l.getData() != null && l.getData().getBodyHash() != null)\r
1036                                                         remoteHash = byteArrayToHexString(l.getData().getBodyHash());\r
1037                                 \r
1038                                                 if (localHash.equalsIgnoreCase(remoteHash))\r
1039                                                         saveNeeded = true;\r
1040                                         }\r
1041                                 }\r
1042                                 \r
1043                                 if (saveNeeded) \r
1044                                         conn.getNoteTable().noteResourceTable.updateNoteResource(r, false);\r
1045 \r
1046                         }\r
1047                 }\r
1048                 logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteResources");\r
1049         }\r
1050         // Sync remote notebooks\r
1051         private void syncRemoteNotes(List<Note> note, boolean fullSync) {\r
1052                 logger.log(logger.EXTREME, "Entering SyncRunner.syncRemoteNotes");\r
1053                 if (note != null) {\r
1054                         for (int i=0; i<note.size() && keepRunning; i++) {\r
1055                                 Note n = getEvernoteNote(note.get(i).getGuid(), true, fullSync, true,true);\r
1056                                 if (n!=null) {\r
1057                                         \r
1058                                         // Basically, this is how the sync logic for a note works.\r
1059                                         // If the remote note has changed and the local has not, we\r
1060                                         // accept the change.\r
1061                                         // If both the local & remote have changed but the sequence\r
1062                                         // numbers are the same, we don't accept the change.  This\r
1063                                         // seems to happen when attachments are indexed by the server.\r
1064                                         // If both the local & remote have changed and the sequence numbers\r
1065                                         // are different we move the local copy to a local notebook (making sure\r
1066                                         // to copy all resources) and we accept the new one.                    \r
1067                                         boolean conflictingNote = true;\r
1068                                         logger.log(logger.EXTREME, "Checking for duplicate note " +n.getGuid());\r
1069                                         if (dirtyNoteGuids.contains(n.getGuid())) { \r
1070                                                 logger.log(logger.EXTREME, "Conflict check beginning");\r
1071                                                 conflictingNote = checkForConflict(n);\r
1072                                                 logger.log(logger.EXTREME, "Conflict check results " +conflictingNote);\r
1073                                                 if (conflictingNote)\r
1074                                                         moveConflictingNote(n.getGuid());\r
1075                                         }\r
1076                                         if (conflictingNote || fullSync) {\r
1077                                                 logger.log(logger.EXTREME, "Saving Note");\r
1078                                                 conn.getNoteTable().syncNote(n, false);\r
1079                                                 noteSignal.noteChanged.emit(n.getGuid(), null);   // Signal to ivalidate note cache\r
1080                                                 noteSignal.noteDownloaded.emit(n, true);                // Signal to add note to index\r
1081                                                 logger.log(logger.EXTREME, "Note Saved");\r
1082                                                 if (fullSync && n.getResources() != null) {\r
1083                                                         for (int q=0; q<n.getResources().size() && keepRunning; q++) {\r
1084                                                                 logger.log(logger.EXTREME, "Getting note resources.");\r
1085                                                                 conn.getNoteTable().noteResourceTable.updateNoteResource(n.getResources().get(q), false);\r
1086                                                         }\r
1087                                                 }\r
1088                                         }\r
1089                                 }\r
1090                         }\r
1091                 }\r
1092                 logger.log(logger.EXTREME, "Leaving SyncRunner.syncRemoteNotes");\r
1093         }\r
1094         private Note getEvernoteNote(String guid, boolean withContent, boolean withResourceData, boolean withResourceRecognition, boolean withResourceAlternateData) { \r
1095                 Note n = null;\r
1096                 try {\r
1097                         logger.log(logger.EXTREME, "Retrieving note " +guid);\r
1098                         n = noteStore.getNote(authToken, guid, withContent, withResourceData, withResourceRecognition, withResourceAlternateData);\r
1099                         logger.log(logger.EXTREME, "Note " +guid +" has been retrieved.");\r
1100                 } catch (EDAMUserException e) {\r
1101                         logger.log(logger.LOW, "*** EDAM User Excepton getEvernoteNote");\r
1102                         logger.log(logger.LOW, e.toString());   \r
1103                         error = true;\r
1104                         e.printStackTrace();\r
1105                 } catch (EDAMSystemException e) {\r
1106                         logger.log(logger.LOW, "*** EDAM System Excepton getEvernoteNote");\r
1107                         logger.log(logger.LOW, e.toString());   \r
1108                         error = true;\r
1109                         e.printStackTrace();\r
1110                 } catch (EDAMNotFoundException e) {\r
1111                         logger.log(logger.LOW, "*** EDAM Not Found Excepton getEvernoteNote");\r
1112                         logger.log(logger.LOW, e.toString());   \r
1113                         error = true;\r
1114                         e.printStackTrace();\r
1115                 } catch (TException e) {\r
1116                         logger.log(logger.LOW, "*** EDAM TExcepton getEvernoteNote");\r
1117                         logger.log(logger.LOW, e.toString());   \r
1118                         error = true;\r
1119                         e.printStackTrace();\r
1120                 }\r
1121                 return n;\r
1122         }\r
1123         private Resource getEvernoteResource(String guid, boolean withData, boolean withRecognition, boolean withAttributes) { \r
1124                 Resource n = null;\r
1125                 try {\r
1126                         logger.log(logger.EXTREME, "Retrieving resource " +guid);\r
1127                         n = noteStore.getResource(authToken, guid, withData, withRecognition, withAttributes, withAttributes);\r
1128                         logger.log(logger.EXTREME, "Resource " +guid +" has been retrieved.");\r
1129                 } catch (EDAMUserException e) {\r
1130                         logger.log(logger.LOW, "*** EDAM User Excepton getEvernoteNote");\r
1131                         logger.log(logger.LOW, e.toString());   \r
1132                         error = true;\r
1133                         e.printStackTrace();\r
1134                 } catch (EDAMSystemException e) {\r
1135                         logger.log(logger.LOW, "*** EDAM System Excepton getEvernoteNote");\r
1136                         logger.log(logger.LOW, e.toString());   \r
1137                         error = true;\r
1138                         e.printStackTrace();\r
1139                 } catch (EDAMNotFoundException e) {\r
1140                         logger.log(logger.LOW, "*** EDAM Not Found Excepton getEvernoteNote");\r
1141                         logger.log(logger.LOW, e.toString());   \r
1142                         error = true;\r
1143                         e.printStackTrace();\r
1144                 } catch (TException e) {\r
1145                         logger.log(logger.LOW, "*** EDAM TExcepton getEvernoteNote");\r
1146                         logger.log(logger.LOW, e.toString());   \r
1147                         error = true;\r
1148                         e.printStackTrace();\r
1149                 }\r
1150                 return n;\r
1151         }\r
1152 \r
1153         \r
1154         private boolean checkForConflict(Note n) {\r
1155                 logger.log(logger.EXTREME, "Checking note sequence number  " +n.getGuid());\r
1156                 Note oldNote = conn.getNoteTable().getNote(n.getGuid(), false, false, false, false, false);\r
1157                 logger.log(logger.EXTREME, "Local/Remote sequence numbers: " +oldNote.getUpdateSequenceNum()+"/"+n.getUpdateSequenceNum());\r
1158                 if (oldNote.getUpdateSequenceNum() == n.getUpdateSequenceNum())\r
1159                         return false;\r
1160                 return true;\r
1161         }\r
1162         \r
1163         private void moveConflictingNote(String guid) {\r
1164                 logger.log(logger.EXTREME, "Conflicting change found for note " +guid);\r
1165                 List<Notebook> books = conn.getNotebookTable().getAllLocal();\r
1166                 String notebookGuid = null;\r
1167                 for (int i=0; i<books.size() && keepRunning; i++) {\r
1168                         if (books.get(i).getName().equalsIgnoreCase("Conflicting Changes (local)") ||\r
1169                                         books.get(i).getName().equalsIgnoreCase("Conflicting Changes")) {\r
1170                                 notebookGuid = books.get(i).getGuid();\r
1171                                 i=books.size();\r
1172                         }\r
1173                 }\r
1174                 \r
1175                 if (notebookGuid == null) {\r
1176                         logger.log(logger.EXTREME, "Building conflicting change notebook " +guid);\r
1177                         Calendar currentTime = new GregorianCalendar();\r
1178                         Long l = new Long(currentTime.getTimeInMillis());\r
1179                         long prevTime = l;\r
1180                         while (prevTime==l) {\r
1181                                 currentTime = new GregorianCalendar();\r
1182                                 l=currentTime.getTimeInMillis();\r
1183                         }\r
1184                         String randint = new String(Long.toString(l));\r
1185                 \r
1186                         Notebook newBook = new Notebook();\r
1187                         newBook.setUpdateSequenceNum(0);\r
1188                         newBook.setGuid(randint);\r
1189                         newBook.setName("Conflicting Changes");\r
1190                         newBook.setServiceCreated(new Date().getTime());\r
1191                         newBook.setServiceUpdated(new Date().getTime());\r
1192                         newBook.setDefaultNotebook(false);\r
1193                         newBook.setPublished(false);\r
1194                         \r
1195                         conn.getNotebookTable().addNotebook(newBook, false, true);\r
1196                         notebookGuid = newBook.getGuid();\r
1197                 }\r
1198                 \r
1199                 // Now that we have a good notebook guid, we need to move the conflicting note\r
1200                 // to the local notebook\r
1201                 logger.log(logger.EXTREME, "Moving conflicting note " +guid);\r
1202                 Calendar currentTime = new GregorianCalendar();\r
1203                 Long l = new Long(currentTime.getTimeInMillis());\r
1204                 long prevTime = l;\r
1205                 while (prevTime==l) {\r
1206                         currentTime = new GregorianCalendar();\r
1207                         l = currentTime.getTimeInMillis();\r
1208                 }\r
1209                 String newGuid = new String(Long.toString(l));\r
1210                                         \r
1211                 Note oldNote = conn.getNoteTable().getNote(guid, true, true, false, false, false);\r
1212                 for (int i=0; i<oldNote.getResources().size() && keepRunning; i++) {\r
1213                         l = new Long(currentTime.getTimeInMillis());\r
1214                         String newResG = new String(Long.toString(l));\r
1215                         String oldResG = oldNote.getResources().get(i).getGuid();\r
1216                         conn.getNoteTable().noteResourceTable.resetUpdateSequenceNumber(oldResG, true);\r
1217                         conn.getNoteTable().noteResourceTable.updateNoteResourceGuid(oldResG, newResG, true);\r
1218                 }\r
1219                 \r
1220                 conn.getNoteTable().resetNoteSequence(guid);\r
1221                 conn.getNoteTable().updateNoteGuid(guid, newGuid);\r
1222                 conn.getNoteTable().updateNoteNotebook(newGuid, notebookGuid, true);\r
1223                 \r
1224                 \r
1225                 noteSignal.guidChanged.emit(guid,newGuid);\r
1226         }\r
1227         \r
1228         \r
1229 \r
1230         \r
1231         //******************************************************\r
1232         //******************************************************\r
1233         //** Utility Functions\r
1234         //******************************************************\r
1235         //******************************************************\r
1236         // Convert a byte array to a hex string\r
1237         private static String byteArrayToHexString(byte data[]) {\r
1238                 StringBuffer buf = new StringBuffer();\r
1239             for (byte element : data) {\r
1240                 int halfbyte = (element >>> 4) & 0x0F;\r
1241                 int two_halfs = 0;\r
1242                 do {\r
1243                         if ((0 <= halfbyte) && (halfbyte <= 9))\r
1244                                buf.append((char) ('0' + halfbyte));\r
1245                            else\r
1246                                 buf.append((char) ('a' + (halfbyte - 10)));\r
1247                         halfbyte = element & 0x0F;\r
1248                 } while(two_halfs++ < 1);\r
1249             }\r
1250             return buf.toString();              \r
1251         }\r
1252 \r
1253         \r
1254         \r
1255         //*******************************************************\r
1256         //* Find dirty tags, which do not have newly created parents\r
1257         //*******************************************************\r
1258         private Tag findNextTag() {\r
1259                 logger.log(logger.HIGH, "Entering SyncRunner.findNextTag");\r
1260                 Tag nextTag = null;\r
1261                 List<Tag> tags = conn.getTagTable().getDirty();\r
1262                 \r
1263                 // Find the parent.  If the parent has a sequence > 0 then it is a good\r
1264                 // parent.\r
1265                 for (int i=0; i<tags.size() && keepRunning; i++) {\r
1266                         if (tags.get(i).getParentGuid() == null) {\r
1267                                 logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - tag found without parent");\r
1268                                 return tags.get(i);\r
1269                         }\r
1270                         Tag parentTag = conn.getTagTable().getTag(tags.get(i).getParentGuid());\r
1271                         if (parentTag.getUpdateSequenceNum() > 0) {\r
1272                                 logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - tag found");\r
1273                                 return tags.get(i);\r
1274                         }\r
1275                 }\r
1276                 \r
1277                 logger.log(logger.HIGH, "Leaving SyncRunner.findNextTag - no tags returned");\r
1278                 return nextTag;\r
1279         }\r
1280         \r
1281         \r
1282            // Connect to Evernote\r
1283     public boolean enConnect()  {\r
1284         try {\r
1285                         userStoreTrans = new THttpClient(userStoreUrl);\r
1286                 } catch (TTransportException e) {\r
1287                         QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage());\r
1288                         mb.exec();\r
1289                         e.printStackTrace();\r
1290                 }\r
1291                 userStoreProt = new TBinaryProtocol(userStoreTrans);\r
1292             userStore = new UserStore.Client(userStoreProt, userStoreProt);\r
1293             syncSignal.saveUserStore.emit(userStore);\r
1294             try {\r
1295                         authResult = userStore.authenticate(username, password, consumerKey, consumerSecret);\r
1296                 } catch (EDAMUserException e) {\r
1297                         QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Error", "Incorrect username/password");\r
1298                         mb.exec();\r
1299                         isConnected = false;\r
1300                         return false;\r
1301                 } catch (EDAMSystemException e) {\r
1302                         QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "EDAM System Excepton", e.getLocalizedMessage());\r
1303                         mb.exec();\r
1304                         e.printStackTrace();\r
1305                         isConnected = false;\r
1306                 } catch (TException e) {\r
1307                         QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage());\r
1308                         mb.exec();\r
1309                         e.printStackTrace();\r
1310                         isConnected = false;\r
1311                 }\r
1312                 \r
1313             boolean versionOk = false;\r
1314                 try {\r
1315 //                      versionOk = userStore.checkVersion("Dave's EDAMDemo (Java)", \r
1316                         versionOk = userStore.checkVersion("NeverNote", \r
1317                     com.evernote.edam.userstore.Constants.EDAM_VERSION_MAJOR, \r
1318                       com.evernote.edam.userstore.Constants.EDAM_VERSION_MINOR);\r
1319                 } catch (TException e) {\r
1320                         e.printStackTrace();\r
1321                         isConnected = false;\r
1322                 } \r
1323             if (!versionOk) { \r
1324                 System.err.println("Incomatible EDAM client protocol version"); \r
1325                 isConnected = false;\r
1326             }\r
1327             if (authResult != null) {\r
1328                 user = authResult.getUser(); \r
1329                 authToken = authResult.getAuthenticationToken(); \r
1330                 noteStoreUrl = noteStoreUrlBase + user.getShardId();\r
1331                 syncSignal.saveAuthToken.emit(authToken);\r
1332                 syncSignal.saveNoteStore.emit(noteStore);\r
1333                 \r
1334          \r
1335                 try {\r
1336                         noteStoreTrans = new THttpClient(noteStoreUrl);\r
1337                 } catch (TTransportException e) {\r
1338                         QMessageBox mb = new QMessageBox(QMessageBox.Icon.Critical, "Transport Excepton", e.getLocalizedMessage());\r
1339                         mb.exec();\r
1340                         e.printStackTrace();\r
1341                         isConnected = false;\r
1342                 } \r
1343                 noteStoreProt = new TBinaryProtocol(noteStoreTrans);\r
1344                 noteStore = \r
1345                         new NoteStore.Client(noteStoreProt, noteStoreProt); \r
1346                 isConnected = true;\r
1347                 authTimeRemaining = authResult.getExpiration() - authResult.getCurrentTime();\r
1348                 authRefreshTime = authTimeRemaining / 2;\r
1349             }\r
1350             \r
1351                 // Get user information\r
1352                 try {\r
1353                         User user = userStore.getUser(authToken);\r
1354                         syncSignal.saveUserInformation.emit(user);\r
1355                 } catch (EDAMUserException e1) {\r
1356                         e1.printStackTrace();\r
1357                 } catch (EDAMSystemException e1) {\r
1358                         e1.printStackTrace();\r
1359                 } catch (TException e1) {\r
1360                         e1.printStackTrace();\r
1361                 }\r
1362             \r
1363             return isConnected;\r
1364     }\r
1365         // Disconnect from the database                         \r
1366     public void enDisconnect() {\r
1367         isConnected = false;\r
1368     }\r
1369     // Refresh the connection\r
1370     private synchronized void refreshConnection() {\r
1371                 logger.log(logger.EXTREME, "Entering SyncRunner.refreshConnection()");\r
1372 //        Calendar cal = Calendar.getInstance();\r
1373                 \r
1374         // If we are not connected let's get out of here\r
1375         if (!isConnected)\r
1376                 return;\r
1377         \r
1378                 // If we fail too many times, then let's give up.\r
1379                 if (failedRefreshes >=5) {\r
1380                         logger.log(logger.EXTREME, "Refresh attempts have failed.  Disconnecting.");\r
1381                         isConnected = false;\r
1382                         return;\r
1383                 }\r
1384         \r
1385                 // If this is the first time through, then we need to set this\r
1386 //              if (authRefreshTime == 0 || cal.getTimeInMillis() > authRefreshTime) \r
1387 //                      authRefreshTime = cal.getTimeInMillis();\r
1388                 \r
1389  //             // Default to checking again in 5 min.  This in case we fail.\r
1390  //             authRefreshTime = authRefreshTime +(5*60*1000);     \r
1391 \r
1392                 // Try to get a new token\r
1393                 AuthenticationResult newAuth = null; \r
1394                 logger.log(logger.EXTREME, "Beginning to try authentication refresh");\r
1395         try {\r
1396                 if (userStore != null && authToken != null) \r
1397                         newAuth = userStore.refreshAuthentication(authToken); \r
1398                 else\r
1399                         return;\r
1400                 logger.log(logger.EXTREME, "UserStore.refreshAuthentication has succeeded.");\r
1401                 } catch (EDAMUserException e) {\r
1402                         e.printStackTrace();\r
1403                         syncSignal.authRefreshComplete.emit(false);\r
1404                         failedRefreshes++;\r
1405                         return;\r
1406                 } catch (EDAMSystemException e) {\r
1407                         e.printStackTrace();\r
1408                         syncSignal.authRefreshComplete.emit(false);\r
1409                         failedRefreshes++;\r
1410                         return;         \r
1411                 } catch (TException e) { \r
1412                         e.printStackTrace();\r
1413                         syncSignal.authRefreshComplete.emit(false);\r
1414                         failedRefreshes++;\r
1415                         return;\r
1416                 }\r
1417                 \r
1418                 // If we didn't get a good auth, then we've failed\r
1419                 if (newAuth == null) {\r
1420                         failedRefreshes++;\r
1421                         logger.log(logger.EXTREME, "Authentication failure #" +failedRefreshes);\r
1422                         syncSignal.authRefreshComplete.emit(false);\r
1423                         return;\r
1424                 }\r
1425                 \r
1426                 // We got a good token.  Now we need to setup the time to renew it.\r
1427                 logger.log(logger.EXTREME, "Saving authentication tokens");\r
1428                 authResult = newAuth;\r
1429                 authToken = new String(newAuth.getAuthenticationToken());\r
1430 //              authTimeRemaining = authResult.getExpiration() - authResult.getCurrentTime();\r
1431 //              authRefreshTime = cal.getTimeInMillis() + (authTimeRemaining/4);        \r
1432                 failedRefreshes=0;\r
1433                 syncSignal.authRefreshComplete.emit(true);\r
1434                 authRefreshNeeded = false;\r
1435                         \r
1436                 // This should never happen, but if it does we consider this a faild attempt.\r
1437 //              if (authTimeRemaining <= 0) {\r
1438 //                      failedRefreshes++;\r
1439 //                      syncSignal.authRefreshComplete.emit(false);\r
1440 //              }\r
1441     }\r
1442     \r
1443         public synchronized boolean addWork(String request) {\r
1444                 if (workQueue.offer(request))\r
1445                         return true;\r
1446                 return false;\r
1447         }\r
1448     \r
1449     private Note getNoteContent(Note n) {\r
1450         n.setContent(conn.getNoteTable().getNoteContentBinary(n.getGuid()));\r
1451         return n;\r
1452     }\r
1453 \r
1454 \r
1455 \r
1456     //*********************************************************\r
1457     //* Special download instructions.  Used for DB upgrades\r
1458     //*********************************************************\r
1459     private void downloadAllSharedNotebooks() {\r
1460         try {\r
1461                         List<SharedNotebook> books = noteStore.listSharedNotebooks(authToken);\r
1462                         logger.log(logger.LOW, "Shared notebooks found = " +books.size());\r
1463                         for (int i=0; i<books.size(); i++) {\r
1464                                 conn.getSharedNotebookTable().updateNotebook(books.get(i), false);\r
1465                         }\r
1466                         conn.getSyncTable().deleteRecord("FullSharedNotebookSync");\r
1467                 } catch (EDAMUserException e1) {\r
1468                         e1.printStackTrace();\r
1469                         status.message.emit(tr("User exception Listing shared notebooks."));\r
1470                         logger.log(logger.LOW, e1.getMessage());\r
1471                         return;\r
1472                 } catch (EDAMSystemException e1) {\r
1473                         e1.printStackTrace();\r
1474                         status.message.emit(tr("System exception Listing shared notebooks."));\r
1475                         logger.log(logger.LOW, e1.getMessage());\r
1476                         return;\r
1477                 } catch (TException e1) {\r
1478                         e1.printStackTrace();\r
1479                         status.message.emit(tr("Transaction exception Listing shared notebooks."));\r
1480                         logger.log(logger.LOW, e1.getMessage());\r
1481                         return;\r
1482                 } catch (EDAMNotFoundException e1) {\r
1483                         e1.printStackTrace();\r
1484                         status.message.emit(tr("EDAM Not Found exception Listing shared notebooks."));\r
1485                         logger.log(logger.LOW, e1.getMessage());\r
1486                 }\r
1487     }\r
1488     private void downloadAllLinkedNotebooks() {\r
1489         try {\r
1490                         List<LinkedNotebook> books = noteStore.listLinkedNotebooks(authToken);\r
1491                         logger.log(logger.LOW, "Linked notebooks found = " +books.size());\r
1492                         for (int i=0; i<books.size(); i++) {\r
1493                                 conn.getLinkedNotebookTable().updateNotebook(books.get(i), false);\r
1494                         }\r
1495                         conn.getSyncTable().deleteRecord("FullLinkedNotebookSync");\r
1496                 } catch (EDAMUserException e1) {\r
1497                         e1.printStackTrace();\r
1498                         status.message.emit(tr("User exception Listing linked notebooks."));\r
1499                         logger.log(logger.LOW, e1.getMessage());\r
1500                         return;\r
1501                 } catch (EDAMSystemException e1) {\r
1502                         e1.printStackTrace();\r
1503                         status.message.emit(tr("System exception Listing linked notebooks."));\r
1504                         logger.log(logger.LOW, e1.getMessage());\r
1505                         return;\r
1506                 } catch (TException e1) {\r
1507                         e1.printStackTrace();\r
1508                         status.message.emit(tr("Transaction exception Listing lineked notebooks."));\r
1509                         logger.log(logger.LOW, e1.getMessage());\r
1510                         return;\r
1511                 } catch (EDAMNotFoundException e1) {\r
1512                         e1.printStackTrace();\r
1513                         status.message.emit(tr("EDAM Not Found exception Listing linked notebooks."));\r
1514                         logger.log(logger.LOW, e1.getMessage());\r
1515                 }\r
1516     }\r
1517 }\r