rhoconnect-client 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +9 -0
- data/CREDITS +0 -0
- data/LICENSE +9 -0
- data/README.md +47 -0
- data/ext/rhoconnect-client/RhoConnectClient.rb +190 -0
- data/ext/rhoconnect-client/ext/RhoConnectClient.xml +726 -0
- data/ext/rhoconnect-client/ext/build +26 -0
- data/ext/rhoconnect-client/ext/build.bat +30 -0
- data/ext/rhoconnect-client/ext/platform/android/ext_java.files +1 -0
- data/ext/rhoconnect-client/ext/platform/android/ext_native.files +14 -0
- data/ext/rhoconnect-client/ext/platform/android/src/com/rhoconnectclient/RhoconnectClient.java +1 -0
- data/ext/rhoconnect-client/ext/platform/iphone/.gitignore +1 -0
- data/ext/rhoconnect-client/ext/platform/iphone/Rakefile +74 -0
- data/ext/rhoconnect-client/ext/platform/iphone/RhoconnectClient.xcodeproj/project.pbxproj +390 -0
- data/ext/rhoconnect-client/ext/platform/iphone/RhoconnectClient_Prefix.pch +7 -0
- data/ext/rhoconnect-client/ext/platform/iphone/impl/readme.txt +7 -0
- data/ext/rhoconnect-client/ext/platform/qt/Rakefile +35 -0
- data/ext/rhoconnect-client/ext/platform/qt/rhoconnect-client.pro +88 -0
- data/ext/rhoconnect-client/ext/platform/wm/Rhoconnect-client.sln +36 -0
- data/ext/rhoconnect-client/ext/platform/wm/Rhoconnect-client.vcproj +774 -0
- data/ext/rhoconnect-client/ext/platform/wm/Rhoconnect-client.vsprops +15 -0
- data/ext/rhoconnect-client/ext/platform/wm/src/rhoconnectclient_wm.cpp +40 -0
- data/ext/rhoconnect-client/ext/platform/wm/src/rhoconnectclient_wm.h +2 -0
- data/ext/rhoconnect-client/ext/platform/wp8/Rhoconnect-client.props +22 -0
- data/ext/rhoconnect-client/ext/platform/wp8/Rhoconnect-client.sln +32 -0
- data/ext/rhoconnect-client/ext/platform/wp8/Rhoconnect-client.vcxproj +220 -0
- data/ext/rhoconnect-client/ext/platform/wp8/Rhoconnect-client.vcxproj.filters +103 -0
- data/ext/rhoconnect-client/ext/shared/RhoConnectClientImpl.cpp +273 -0
- data/ext/rhoconnect-client/ext/shared/RhoConnectClientImpl.h +60 -0
- data/ext/rhoconnect-client/ext/shared/RhoConnectClientSingletonImpl.h +53 -0
- data/ext/rhoconnect-client/ext/shared/initRhoconnectClient.cpp +207 -0
- data/ext/rhoconnect-client/ext/shared/rhoconnectclient.c +18 -0
- data/ext/rhoconnect-client/ext/shared/sync/ClientRegister.cpp +398 -0
- data/ext/rhoconnect-client/ext/shared/sync/ClientRegister.h +147 -0
- data/ext/rhoconnect-client/ext/shared/sync/ISyncProtocol.h +91 -0
- data/ext/rhoconnect-client/ext/shared/sync/SyncEngine.cpp +1245 -0
- data/ext/rhoconnect-client/ext/shared/sync/SyncEngine.h +213 -0
- data/ext/rhoconnect-client/ext/shared/sync/SyncNotify.cpp +737 -0
- data/ext/rhoconnect-client/ext/shared/sync/SyncNotify.h +209 -0
- data/ext/rhoconnect-client/ext/shared/sync/SyncProtocol_3.h +220 -0
- data/ext/rhoconnect-client/ext/shared/sync/SyncProtocol_4.h +259 -0
- data/ext/rhoconnect-client/ext/shared/sync/SyncSource.cpp +1694 -0
- data/ext/rhoconnect-client/ext/shared/sync/SyncSource.h +212 -0
- data/ext/rhoconnect-client/ext/shared/sync/SyncThread.cpp +583 -0
- data/ext/rhoconnect-client/ext/shared/sync/SyncThread.h +250 -0
- data/ext/rhoconnect-client/ext.yml +12 -0
- data/lib/build/run_rhoconnect_spec.rb +135 -0
- data/lib/rhoconnect-client.rb +3 -0
- data/platform/shared/RhoConnectClient/RhoConnectClient.cpp +1673 -0
- data/platform/shared/RhoConnectClient/RhoConnectClient.h +181 -0
- data/platform/shared/RhoConnectClient/RhoError.h +77 -0
- data/rhoconnect-client/C++/Tests/RhoConnectClientTest.cpp +830 -0
- data/rhoconnect-client/C++/Tests/win32/.gitignore +3 -0
- data/rhoconnect-client/C++/Tests/win32/RhoConnectClient.sln +65 -0
- data/rhoconnect-client/C++/Tests/win32/RhoConnectClient.vcproj +634 -0
- data/rhoconnect-client/C++/Tests/win32/RhoConnectClientTest/RhoConnectClientTest.vcproj +222 -0
- data/rhoconnect-client/C++/Tests/win32/RhoConnectClientTest/stdafx.h +65 -0
- data/rhoconnect-client/C++/Tests/win32/stdafx.h +65 -0
- data/rhoconnect-client/CHANGELOG +18 -0
- data/rhoconnect-client/Java/Android/build/android.rake +387 -0
- data/rhoconnect-client/Java/Android/build/android_sdk.rb +582 -0
- data/rhoconnect-client/Java/Android/build/libcurl_build.files +73 -0
- data/rhoconnect-client/Java/Android/build/libjson_build.files +9 -0
- data/rhoconnect-client/Java/Android/build/librhocommon_build.files +14 -0
- data/rhoconnect-client/Java/Android/build/librhodb_build.files +5 -0
- data/rhoconnect-client/Java/Android/build/librhoimpl_build.files +13 -0
- data/rhoconnect-client/Java/Android/build/librholog_build.files +4 -0
- data/rhoconnect-client/Java/Android/build/libsqlite_build.files +1 -0
- data/rhoconnect-client/Java/Android/build/libsync_build.files +7 -0
- data/rhoconnect-client/Java/Android/build/libunzip_build.files +1 -0
- data/rhoconnect-client/Java/Android/build/rhoconnectclient_build.files +3 -0
- data/rhoconnect-client/Java/Android/build/rhoimpljava_build.files +21 -0
- data/rhoconnect-client/Java/Android/src/com/rhomobile/rhodes/Capabilities.java +63 -0
- data/rhoconnect-client/Java/Android/src/com/rhomobile/rhodes/MemoryInfoCollector.java +79 -0
- data/rhoconnect-client/Java/Android/src/com/rhomobile/rhodes/util/ContextFactory.java +63 -0
- data/rhoconnect-client/Java/Android/test/.classpath +9 -0
- data/rhoconnect-client/Java/Android/test/.project +33 -0
- data/rhoconnect-client/Java/Android/test/AndroidManifest.xml +14 -0
- data/rhoconnect-client/Java/Android/test/assets/apps/androidtest.png +0 -0
- data/rhoconnect-client/Java/Android/test/assets/apps/rhoconfig.txt +19 -0
- data/rhoconnect-client/Java/Android/test/assets/apps/rhoconfig.txt.timestamp +1 -0
- data/rhoconnect-client/Java/Android/test/assets/db/syncdb.schema +44 -0
- data/rhoconnect-client/Java/Android/test/assets/db/syncdb.triggers +10 -0
- data/rhoconnect-client/Java/Android/test/assets/db/syncdb_java.triggers +21 -0
- data/rhoconnect-client/Java/Android/test/assets/rho.dat +9 -0
- data/rhoconnect-client/Java/Android/test/proguard.cfg +36 -0
- data/rhoconnect-client/Java/Android/test/project.properties +11 -0
- data/rhoconnect-client/Java/Android/test/res/drawable-hdpi/icon.png +0 -0
- data/rhoconnect-client/Java/Android/test/res/drawable-ldpi/icon.png +0 -0
- data/rhoconnect-client/Java/Android/test/res/drawable-mdpi/icon.png +0 -0
- data/rhoconnect-client/Java/Android/test/res/layout/main.xml +12 -0
- data/rhoconnect-client/Java/Android/test/res/values/strings.xml +5 -0
- data/rhoconnect-client/Java/Android/test/rhoimpl.jar +0 -0
- data/rhoconnect-client/Java/Android/test/src/com/rhomobile/rhoconnect_client_test/TestRhoConnectClient.java +343 -0
- data/rhoconnect-client/Java/Android/test/src/com/rhomobile/rhoconnect_client_test/TestRhoConnectClientBlobs.java +219 -0
- data/rhoconnect-client/Java/RhoConnect/.classpath +6 -0
- data/rhoconnect-client/Java/RhoConnect/.project +93 -0
- data/rhoconnect-client/Java/RhoConnect/assets/apps/rhoconfig.txt +19 -0
- data/rhoconnect-client/Java/RhoConnect/assets/apps/rhoconfig.txt.timestamp +1 -0
- data/rhoconnect-client/Java/RhoConnect/assets/db/syncdb.schema +44 -0
- data/rhoconnect-client/Java/RhoConnect/assets/db/syncdb.triggers +10 -0
- data/rhoconnect-client/Java/RhoConnect/assets/db/syncdb_java.triggers +21 -0
- data/rhoconnect-client/Java/RhoConnect/assets/rho.dat +8 -0
- data/rhoconnect-client/Java/RhoConnect/jni/include/RhoConnectJniNotify.h +61 -0
- data/rhoconnect-client/Java/RhoConnect/jni/include/com_rhomobile_rhoconnect_RhoConnectClient.h +181 -0
- data/rhoconnect-client/Java/RhoConnect/jni/include/com_rhomobile_rhoconnect_RhoConnectNotify.h +13 -0
- data/rhoconnect-client/Java/RhoConnect/jni/include/com_rhomobile_rhoconnect_RhoConnectNotify_IDelegate.h +13 -0
- data/rhoconnect-client/Java/RhoConnect/jni/include/com_rhomobile_rhoconnect_RhoConnectObjectNotify.h +13 -0
- data/rhoconnect-client/Java/RhoConnect/jni/include/com_rhomobile_rhoconnect_RhoConnectObjectNotify_IDelegate.h +13 -0
- data/rhoconnect-client/Java/RhoConnect/jni/include/com_rhomobile_rhoconnect_RhomModel.h +103 -0
- data/rhoconnect-client/Java/RhoConnect/jni/include/rhojava.inc +76 -0
- data/rhoconnect-client/Java/RhoConnect/jni/src/RhoConnectJniClient.cpp +401 -0
- data/rhoconnect-client/Java/RhoConnect/jni/src/RhoConnectJniModel.cpp +332 -0
- data/rhoconnect-client/Java/RhoConnect/jni/src/RhoConnectJniNotify.cpp +223 -0
- data/rhoconnect-client/Java/RhoConnect/jni/src/RhoConnectUtil.cpp +82 -0
- data/rhoconnect-client/Java/RhoConnect/jni/src/RhodesApp.cpp +114 -0
- data/rhoconnect-client/Java/RhoConnect/src/com/rhomobile/rhoconnect/RhoConnectClient.java +108 -0
- data/rhoconnect-client/Java/RhoConnect/src/com/rhomobile/rhoconnect/RhoConnectNotify.java +78 -0
- data/rhoconnect-client/Java/RhoConnect/src/com/rhomobile/rhoconnect/RhoConnectObjectNotify.java +71 -0
- data/rhoconnect-client/Java/RhoConnect/src/com/rhomobile/rhoconnect/RhomModel.java +195 -0
- data/rhoconnect-client/JavaScript/.classpath +10 -0
- data/rhoconnect-client/JavaScript/.gitignore +4 -0
- data/rhoconnect-client/JavaScript/.project +17 -0
- data/rhoconnect-client/JavaScript/README.textile +1 -0
- data/rhoconnect-client/JavaScript/build.xml +185 -0
- data/rhoconnect-client/JavaScript/doc/fsm-sample.js +44 -0
- data/rhoconnect-client/JavaScript/doc/fsm-sample.png +0 -0
- data/rhoconnect-client/JavaScript/src/RhoSyncJS.gwt.xml +21 -0
- data/rhoconnect-client/JavaScript/stubs/RhoSyncStubsJS.gwt.xml +21 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/Capabilities.java +7 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/IRhoRubyHelper.java +7 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/Mutex.java +5 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/RhoAppAdapter.java +39 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/RhoClassFactory.java +29 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/RhoConf.java +100 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/RhoEmptyLogger.java +7 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/RhoEmptyProfiler.java +5 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/RhoLogger.java +32 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/RhoProfiler.java +27 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/RhodesApp.java +25 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/TimeInterval.java +22 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/Tokenizer.java +23 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/db/DBAdapter.java +174 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/db/DBAttrManager.java +15 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/db/DBException.java +5 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/db/IDBResult.java +27 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/file/IFileAccess.java +7 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/file/SimpleFile.java +15 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/net/IHttpConnection.java +22 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/net/NetRequest.java +324 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/net/NetResponse.java +51 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/net/URI.java +64 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/sync/ClientRegister.java +15 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/sync/JSONArrayIterator.java +37 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/sync/JSONEntry.java +48 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/sync/JSONStructIterator.java +41 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/sync/SyncNotify.java +98 -0
- data/rhoconnect-client/JavaScript/stubs/com/rho/sync/SyncThread.java +92 -0
- data/rhoconnect-client/JavaScript/war/WEB-INF/lib/gwt-servlet-deps.jar +0 -0
- data/rhoconnect-client/JavaScript/war/WEB-INF/lib/gwt-servlet.jar +0 -0
- data/rhoconnect-client/JavaScript/war/js/fsm-sample.js +54 -0
- data/rhoconnect-client/JavaScript/war/js/rhosync-api.js +237 -0
- data/rhoconnect-client/JavaScript/war/js/rhosync-fsm.js +307 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/4C71D69C9BBC9E6F05C6BA49B01BCBC1.cache.html +3122 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/5146F4FFF34511C8BB2661E920B49E3A.cache.html +3254 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/5248C67481D9D27AD0703D15CDBD2A1C.cache.html +3147 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/EE1DC2692C9C32367B53A39E2358AF23.cache.html +3195 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/clear.cache.gif +0 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/gwt/standard/images/corner.png +0 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/gwt/standard/images/corner_ie6.png +0 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/gwt/standard/images/hborder.png +0 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/gwt/standard/images/hborder_ie6.png +0 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/gwt/standard/images/ie6/corner_dialog_topleft.png +0 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/gwt/standard/images/ie6/corner_dialog_topright.png +0 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/gwt/standard/images/ie6/hborder_blue_shadow.png +0 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/gwt/standard/images/ie6/hborder_gray_shadow.png +0 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/gwt/standard/images/ie6/vborder_blue_shadow.png +0 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/gwt/standard/images/ie6/vborder_gray_shadow.png +0 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/gwt/standard/images/splitPanelThumb.png +0 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/gwt/standard/images/vborder.png +0 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/gwt/standard/images/vborder_ie6.png +0 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/gwt/standard/standard.css +1144 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/gwt/standard/standard_rtl.css +1145 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/hosted.html +350 -0
- data/rhoconnect-client/JavaScript/war/rhosyncjs/rhosyncjs.nocache.js +314 -0
- data/rhoconnect-client/JavaScript/war/test/SpecRunner.html +35 -0
- data/rhoconnect-client/JavaScript/war/test/dbtest.html +38 -0
- data/rhoconnect-client/JavaScript/war/test/lib/jasmine-1.0.1/MIT.LICENSE +20 -0
- data/rhoconnect-client/JavaScript/war/test/lib/jasmine-1.0.1/jasmine-html.js +188 -0
- data/rhoconnect-client/JavaScript/war/test/lib/jasmine-1.0.1/jasmine.css +166 -0
- data/rhoconnect-client/JavaScript/war/test/lib/jasmine-1.0.1/jasmine.js +2421 -0
- data/rhoconnect-client/JavaScript/war/test/spec/SpecHelper.js +7 -0
- data/rhoconnect-client/JavaScript/war/test/spec/SyncApiSpec.js +573 -0
- data/rhoconnect-client/JavaScript/war/test/spec/samples/PlayerSpec.js +58 -0
- data/rhoconnect-client/JavaScript/war/test/worker-test.js +17 -0
- data/rhoconnect-client/LICENSE +41 -0
- data/rhoconnect-client/ObjectiveC/RhoConnectClient.h +118 -0
- data/rhoconnect-client/ObjectiveC/RhoConnectClient.m +641 -0
- data/rhoconnect-client/ObjectiveC/RhoConnectClient.xcodeproj/project.pbxproj +1434 -0
- data/rhoconnect-client/ObjectiveC/RhoConnectNotify.h +83 -0
- data/rhoconnect-client/ObjectiveC/RhoConnectNotify.m +181 -0
- data/rhoconnect-client/ObjectiveC/RhoConnectObjectNotify.h +65 -0
- data/rhoconnect-client/ObjectiveC/RhoConnectObjectNotify.m +73 -0
- data/rhoconnect-client/ObjectiveC/RhomModel.h +101 -0
- data/rhoconnect-client/ObjectiveC/RhomModel.m +320 -0
- data/rhoconnect-client/ObjectiveC/Tests/RhoConnectClientTest/MainWindow.xib +198 -0
- data/rhoconnect-client/ObjectiveC/Tests/RhoConnectClientTest/RhoConnectClientTest-Info.plist +30 -0
- data/rhoconnect-client/ObjectiveC/Tests/RhoConnectClientTest/RhoConnectClientTest.xcodeproj/project.pbxproj +373 -0
- data/rhoconnect-client/ObjectiveC/Tests/RhoConnectClientTest/RhoConnectClientTestAppDelegate.h +58 -0
- data/rhoconnect-client/ObjectiveC/Tests/RhoConnectClientTest/RhoConnectClientTestAppDelegate.m +84 -0
- data/rhoconnect-client/ObjectiveC/Tests/RhoConnectClientTest/RhoConnectClientTest_Prefix.pch +8 -0
- data/rhoconnect-client/ObjectiveC/Tests/RhoConnectClientTest/invalid_import_db.zip +0 -0
- data/rhoconnect-client/ObjectiveC/Tests/RhoConnectClientTest/main.m +1096 -0
- data/rhoconnect-client/ObjectiveC/Tests/RhoConnectClientTest/test.png +0 -0
- data/rhoconnect-client/ObjectiveC/Tests/RhoConnectClientTest/test2.png +0 -0
- data/rhoconnect-client/ObjectiveC/Tests/RhoConnectClientTest/valid_import_db.zip +0 -0
- data/rhoconnect-client/ObjectiveC/Tests/ptests/Classes/ptestsAppDelegate.h +62 -0
- data/rhoconnect-client/ObjectiveC/Tests/ptests/Classes/ptestsAppDelegate.m +35 -0
- data/rhoconnect-client/ObjectiveC/Tests/ptests/Classes/ptestsViewController.h +78 -0
- data/rhoconnect-client/ObjectiveC/Tests/ptests/Classes/ptestsViewController.m +549 -0
- data/rhoconnect-client/ObjectiveC/Tests/ptests/MainWindow.xib +227 -0
- data/rhoconnect-client/ObjectiveC/Tests/ptests/main.m +17 -0
- data/rhoconnect-client/ObjectiveC/Tests/ptests/ptests-Info.plist +30 -0
- data/rhoconnect-client/ObjectiveC/Tests/ptests/ptests.xcodeproj/project.pbxproj +363 -0
- data/rhoconnect-client/ObjectiveC/Tests/ptests/ptestsViewController.xib +641 -0
- data/rhoconnect-client/ObjectiveC/Tests/ptests/ptests_Prefix.pch +8 -0
- data/rhoconnect-client/README.textile +23 -0
- data/rhoconnect-client/Rakefile +20 -0
- data/rhoconnect-client/Samples/Java/android_store/.classpath +8 -0
- data/rhoconnect-client/Samples/Java/android_store/.project +33 -0
- data/rhoconnect-client/Samples/Java/android_store/AndroidManifest.xml +24 -0
- data/rhoconnect-client/Samples/Java/android_store/assets/apps/rhoconfig.txt +19 -0
- data/rhoconnect-client/Samples/Java/android_store/assets/apps/rhoconfig.txt.timestamp +1 -0
- data/rhoconnect-client/Samples/Java/android_store/assets/db/syncdb.schema +44 -0
- data/rhoconnect-client/Samples/Java/android_store/assets/db/syncdb.triggers +10 -0
- data/rhoconnect-client/Samples/Java/android_store/assets/db/syncdb_java.triggers +21 -0
- data/rhoconnect-client/Samples/Java/android_store/assets/rho.dat +8 -0
- data/rhoconnect-client/Samples/Java/android_store/default.properties +11 -0
- data/rhoconnect-client/Samples/Java/android_store/project.properties +14 -0
- data/rhoconnect-client/Samples/Java/android_store/res/drawable-hdpi/icon.png +0 -0
- data/rhoconnect-client/Samples/Java/android_store/res/drawable-ldpi/icon.png +0 -0
- data/rhoconnect-client/Samples/Java/android_store/res/drawable-mdpi/icon.png +0 -0
- data/rhoconnect-client/Samples/Java/android_store/res/layout/main.xml +12 -0
- data/rhoconnect-client/Samples/Java/android_store/res/values/strings.xml +5 -0
- data/rhoconnect-client/Samples/Java/android_store/rhoimpl.jar +0 -0
- data/rhoconnect-client/Samples/Java/android_store/src/com/rhomobile/android_store/StoreActivity.java +68 -0
- data/rhoconnect-client/Samples/Java/android_store/src/com/rhomobile/android_store/StoreApplication.java +15 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/Classes/LoginViewController.h +70 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/Classes/LoginViewController.m +94 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/Classes/RhoConnectEngine.h +82 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/Classes/RhoConnectEngine.m +119 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/Classes/RootViewController.h +63 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/Classes/RootViewController.m +314 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/Classes/WaitLoginController.h +65 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/Classes/WaitLoginController.m +110 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/Classes/storeAppDelegate.h +61 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/Classes/storeAppDelegate.m +171 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/LoginViewController.xib +779 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/MainWindow.xib +580 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/RootViewController.xib +384 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/WaitLoginController.xib +557 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/icon.png +0 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/main.m +22 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/store-Info.plist +30 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/store.xcodeproj/project.pbxproj +367 -0
- data/rhoconnect-client/Samples/ObjectiveC/store/store_Prefix.pch +14 -0
- data/rhoconnect-client/build.yml +3 -0
- data/rhoconnect-client/version +1 -0
- metadata +314 -0
|
@@ -0,0 +1,1694 @@
|
|
|
1
|
+
/*------------------------------------------------------------------------
|
|
2
|
+
* (The MIT License)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2008-2011 Rhomobile, Inc.
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in
|
|
14
|
+
* all copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
22
|
+
* THE SOFTWARE.
|
|
23
|
+
*
|
|
24
|
+
* http://rhomobile.com
|
|
25
|
+
|
|
26
|
+
* Copyright (c) 2011-2016 Symbol Technologies, Inc.
|
|
27
|
+
*
|
|
28
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
29
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
30
|
+
* in the Software without restriction, including without limitation the rights
|
|
31
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
32
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
33
|
+
* furnished to do so, subject to the following conditions:
|
|
34
|
+
*
|
|
35
|
+
* The above copyright notice and this permission notice shall be included in
|
|
36
|
+
* all copies or substantial portions of the Software.
|
|
37
|
+
*
|
|
38
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
39
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
40
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
41
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
42
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
43
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
44
|
+
* THE SOFTWARE.
|
|
45
|
+
*
|
|
46
|
+
* http://symbol.com
|
|
47
|
+
*------------------------------------------------------------------------*/
|
|
48
|
+
|
|
49
|
+
#include "SyncSource.h"
|
|
50
|
+
#include "SyncEngine.h"
|
|
51
|
+
#include "SyncThread.h"
|
|
52
|
+
|
|
53
|
+
#include "common/RhoTime.h"
|
|
54
|
+
#include "common/StringConverter.h"
|
|
55
|
+
#include "common/RhodesApp.h"
|
|
56
|
+
#include "common/Tokenizer.h"
|
|
57
|
+
#include "common/RhoFilePath.h"
|
|
58
|
+
#include "common/RhoFile.h"
|
|
59
|
+
#include "common/RhoAppAdapter.h"
|
|
60
|
+
#include "common/RhoConf.h"
|
|
61
|
+
#include "json/JSONIterator.h"
|
|
62
|
+
#include "statistic/RhoProfiler.h"
|
|
63
|
+
#include "net/URI.h"
|
|
64
|
+
#ifndef RHO_NO_RUBY
|
|
65
|
+
#include "ruby/ext/rho/rhoruby.h"
|
|
66
|
+
#endif //RHO_NO_RUBY
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
namespace rho {
|
|
70
|
+
namespace sync {
|
|
71
|
+
IMPLEMENT_LOGCLASS(CSyncSource,"Sync");
|
|
72
|
+
|
|
73
|
+
using namespace rho::net;
|
|
74
|
+
using namespace rho::db;
|
|
75
|
+
using namespace rho::common;
|
|
76
|
+
using namespace rho::json;
|
|
77
|
+
/*
|
|
78
|
+
CSyncSource::CSyncSource() : m_syncEngine( *new CSyncEngine(*new db::CDBAdapter()))
|
|
79
|
+
{
|
|
80
|
+
m_bTokenFromDB = true;
|
|
81
|
+
|
|
82
|
+
m_nCurPageCount = 0;
|
|
83
|
+
m_nInserted = 0;
|
|
84
|
+
m_nDeleted = 0;
|
|
85
|
+
m_nTotalCount = 0;
|
|
86
|
+
|
|
87
|
+
m_nErrCode = RhoAppAdapter.ERR_NONE;
|
|
88
|
+
|
|
89
|
+
m_bIsSearch = false;
|
|
90
|
+
}
|
|
91
|
+
*/
|
|
92
|
+
CSyncSource::CSyncSource(CSyncEngine& syncEngine, db::CDBAdapter& db ) : m_syncEngine(syncEngine), m_dbAdapter(db)
|
|
93
|
+
{
|
|
94
|
+
m_bTokenFromDB = true;
|
|
95
|
+
m_nProgressStep = 0;
|
|
96
|
+
m_nCurPageCount = 0;
|
|
97
|
+
m_nInserted = 0;
|
|
98
|
+
m_nDeleted = 0;
|
|
99
|
+
m_nTotalCount = 0;
|
|
100
|
+
m_nRefreshTime = 0;
|
|
101
|
+
|
|
102
|
+
m_nErrCode = RhoAppAdapter.ERR_NONE;
|
|
103
|
+
m_bSchemaSource = db.isTableExist(m_strName);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
CSyncSource::CSyncSource(int id, const String& strName, const String& strSyncType, db::CDBAdapter& db, CSyncEngine& syncEngine ) : m_syncEngine(syncEngine), m_dbAdapter(db)
|
|
107
|
+
{
|
|
108
|
+
m_nID = id;
|
|
109
|
+
m_strName = strName;
|
|
110
|
+
m_strSyncType = strSyncType;
|
|
111
|
+
m_nProgressStep = 0;
|
|
112
|
+
|
|
113
|
+
m_nCurPageCount = 0;
|
|
114
|
+
m_nInserted = 0;
|
|
115
|
+
m_nDeleted = 0;
|
|
116
|
+
m_nTotalCount = 0;
|
|
117
|
+
m_nRefreshTime = 0;
|
|
118
|
+
|
|
119
|
+
m_nErrCode = RhoAppAdapter.ERR_NONE;
|
|
120
|
+
|
|
121
|
+
IDBResult res = db.executeSQL("SELECT token,associations from sources WHERE source_id=?", m_nID);
|
|
122
|
+
if ( !res.isEnd() )
|
|
123
|
+
{
|
|
124
|
+
m_token = res.getUInt64ByIdx(0);
|
|
125
|
+
m_bTokenFromDB = true;
|
|
126
|
+
}else
|
|
127
|
+
{
|
|
128
|
+
m_token = 0;
|
|
129
|
+
m_bTokenFromDB = true;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
m_bSchemaSource = db.isTableExist(m_strName);
|
|
133
|
+
parseAssociations(res.getStringByIdx(1));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
void CSyncSource::parseAssociations(const String& strAssociations)
|
|
137
|
+
{
|
|
138
|
+
if (strAssociations.length() == 0 )
|
|
139
|
+
return;
|
|
140
|
+
|
|
141
|
+
CTokenizer oTokenizer( strAssociations, "," );
|
|
142
|
+
|
|
143
|
+
String strSrcName = "";
|
|
144
|
+
while (oTokenizer.hasMoreTokens())
|
|
145
|
+
{
|
|
146
|
+
String tok = oTokenizer.nextToken();
|
|
147
|
+
if (tok.length() == 0)
|
|
148
|
+
continue;
|
|
149
|
+
|
|
150
|
+
if ( strSrcName.length() > 0 )
|
|
151
|
+
{
|
|
152
|
+
m_arAssociations.addElement( CAssociation(strSrcName, tok) );
|
|
153
|
+
strSrcName = "";
|
|
154
|
+
}else
|
|
155
|
+
strSrcName = tok;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
net::CNetRequestWrapper CSyncSource::getNet(){ return getSync().getNet(); }
|
|
160
|
+
CSyncNotify& CSyncSource::getNotify(){ return getSync().getNotify(); }
|
|
161
|
+
ISyncProtocol& CSyncSource::getProtocol(){ return getSync().getProtocol(); }
|
|
162
|
+
|
|
163
|
+
void CSyncSource::sync()
|
|
164
|
+
{
|
|
165
|
+
getNotify().reportSyncStatus(RhoAppAdapter.getMessageText("syncronizing") + getName() + "...", m_nErrCode, m_strError );
|
|
166
|
+
|
|
167
|
+
CTimeInterval startTime = CTimeInterval::getCurrentTime();
|
|
168
|
+
//m_bIsSearch = false;
|
|
169
|
+
|
|
170
|
+
// if ( isTokenFromDB() && getToken() > 1 )
|
|
171
|
+
// syncServerChanges(); //sync only server changes, which was paused before
|
|
172
|
+
// else
|
|
173
|
+
// {
|
|
174
|
+
if ( isEmptyToken() )
|
|
175
|
+
processToken(1);
|
|
176
|
+
|
|
177
|
+
syncClientChanges();
|
|
178
|
+
syncServerChanges();
|
|
179
|
+
|
|
180
|
+
/*
|
|
181
|
+
boolean bSyncedServer = syncClientChanges();
|
|
182
|
+
if ( !bSyncedServer )
|
|
183
|
+
syncServerChanges();
|
|
184
|
+
*/
|
|
185
|
+
// }
|
|
186
|
+
|
|
187
|
+
CTimeInterval endTime = CTimeInterval::getCurrentTime();
|
|
188
|
+
|
|
189
|
+
int nSyncSucess = m_nErrCode == RhoAppAdapter.ERR_NONE ? 1 : 0;
|
|
190
|
+
if ( nSyncSucess > 0 )
|
|
191
|
+
getDB().executeSQL( "UPDATE sources set last_updated=?,last_inserted_size=?,last_deleted_size=?, \
|
|
192
|
+
last_sync_duration=?,last_sync_success=?, backend_refresh_time=? WHERE source_id=?",
|
|
193
|
+
CLocalTime().toULong(), getInsertedCount(), getDeletedCount(), (endTime-startTime).toULong(), nSyncSucess, m_nRefreshTime,
|
|
194
|
+
getID() );
|
|
195
|
+
else
|
|
196
|
+
getDB().executeSQL( "UPDATE sources set last_inserted_size=?,last_deleted_size=?, \
|
|
197
|
+
last_sync_duration=?,last_sync_success=?, backend_refresh_time=? WHERE source_id=?",
|
|
198
|
+
getInsertedCount(), getDeletedCount(), (endTime-startTime).toULong(), nSyncSucess, m_nRefreshTime,
|
|
199
|
+
getID() );
|
|
200
|
+
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
void CSyncSource::syncClientChanges()
|
|
204
|
+
{
|
|
205
|
+
PROF_START("Pull");
|
|
206
|
+
|
|
207
|
+
boolean bSyncClient = haveChangedValues();
|
|
208
|
+
|
|
209
|
+
if ( bSyncClient )
|
|
210
|
+
doSyncClientChanges();
|
|
211
|
+
|
|
212
|
+
PROF_STOP("Pull");
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/*
|
|
216
|
+
boolean CSyncSource::syncClientChanges()
|
|
217
|
+
{
|
|
218
|
+
boolean bSyncedServer = false;
|
|
219
|
+
if ( isPendingClientChanges() )
|
|
220
|
+
{
|
|
221
|
+
LOG(INFO) + "Client has unconfirmed created items. Call server to update them.";
|
|
222
|
+
syncServerChanges();
|
|
223
|
+
bSyncedServer = true;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if ( bSyncedServer && isPendingClientChanges() )
|
|
227
|
+
{
|
|
228
|
+
LOG(INFO) + "Server does not sent created items. Stop sync.";
|
|
229
|
+
getSync().setState(CSyncEngine::esStop);
|
|
230
|
+
}
|
|
231
|
+
else
|
|
232
|
+
{
|
|
233
|
+
PROF_START("Pull");
|
|
234
|
+
|
|
235
|
+
boolean bSyncClient = false;
|
|
236
|
+
{
|
|
237
|
+
IDBResult res = getDB().executeSQL("SELECT object FROM changed_values WHERE source_id=? LIMIT 1 OFFSET 0", getID());
|
|
238
|
+
bSyncClient = !res.isEnd();
|
|
239
|
+
}
|
|
240
|
+
if ( bSyncClient )
|
|
241
|
+
{
|
|
242
|
+
doSyncClientChanges();
|
|
243
|
+
bSyncedServer = false;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
PROF_STOP("Pull");
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return bSyncedServer;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
boolean CSyncSource::isPendingClientChanges()
|
|
253
|
+
{
|
|
254
|
+
IDBResult res = getDB().executeSQL("SELECT object FROM changed_values WHERE source_id=? and update_type='create' and sent>1 LIMIT 1 OFFSET 0", getID());
|
|
255
|
+
return !res.isEnd();
|
|
256
|
+
}*/
|
|
257
|
+
|
|
258
|
+
void CSyncSource::addBelongsTo(const String& strAttrib, int nSrcID)
|
|
259
|
+
{
|
|
260
|
+
m_hashBelongsTo.put(strAttrib, nSrcID);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
int CSyncSource::getBelongsToSrcID(const String& strAttrib)
|
|
264
|
+
{
|
|
265
|
+
if ( m_hashBelongsTo.containsKey(strAttrib) )
|
|
266
|
+
return m_hashBelongsTo.get(strAttrib);
|
|
267
|
+
|
|
268
|
+
return -1;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
void CSyncSource::checkIgnorePushObjects()
|
|
272
|
+
{
|
|
273
|
+
// ignore changes in pending creates
|
|
274
|
+
{
|
|
275
|
+
IDBResult res = getDB().executeSQL("SELECT distinct(object) FROM changed_values where source_id=? and sent>=2", getID() );
|
|
276
|
+
for( ; !res.isEnd(); res.next() )
|
|
277
|
+
{
|
|
278
|
+
String strObject = res.getStringByIdx(0);
|
|
279
|
+
m_hashIgnorePushObjects.put(strObject, 1);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
//check for belongs_to
|
|
284
|
+
String strAttribQuests = "";
|
|
285
|
+
Vector<String> arValues;
|
|
286
|
+
arValues.addElement(convertToStringA(getID()));
|
|
287
|
+
for ( Hashtable<String,int>::iterator it = m_hashBelongsTo.begin(); it != m_hashBelongsTo.end(); ++it )
|
|
288
|
+
{
|
|
289
|
+
if ( strAttribQuests.length() > 0 )
|
|
290
|
+
strAttribQuests += ",";
|
|
291
|
+
|
|
292
|
+
strAttribQuests += "?";
|
|
293
|
+
arValues.addElement(it->first);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if ( strAttribQuests.length() > 0 )
|
|
297
|
+
{
|
|
298
|
+
IDBResult res = getDB().executeSQLEx( (String("SELECT object, attrib, value FROM changed_values where source_id=? and sent<=1 and attrib IN ( ") + strAttribQuests + " )").c_str(),
|
|
299
|
+
arValues );
|
|
300
|
+
|
|
301
|
+
for( ; !res.isEnd(); res.next() )
|
|
302
|
+
{
|
|
303
|
+
String strObject = res.getStringByIdx(0);
|
|
304
|
+
String strAttrib = res.getStringByIdx(1);
|
|
305
|
+
String strValue = res.getStringByIdx(2);
|
|
306
|
+
|
|
307
|
+
IDBResult res2 = getDB().executeSQL(
|
|
308
|
+
"SELECT object FROM changed_values where source_id=? and sent>=2 and object=? LIMIT 1 OFFSET 0",
|
|
309
|
+
getBelongsToSrcID(strAttrib), strValue );
|
|
310
|
+
|
|
311
|
+
if (!res2.isEnd())
|
|
312
|
+
m_hashIgnorePushObjects.put(strObject, 1);
|
|
313
|
+
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
void CSyncSource::doSyncClientChanges()
|
|
319
|
+
{
|
|
320
|
+
String arUpdateTypes[] = {"create", "update", "delete"};
|
|
321
|
+
boolean arUpdateSent[] = {false, false, false};
|
|
322
|
+
|
|
323
|
+
m_arMultipartItems.removeAllElements();
|
|
324
|
+
m_arBlobAttrs.removeAllElements();
|
|
325
|
+
String strBody = "{\"source_name\":" + CJSONEntry::quoteValue(getName()) + ",\"client_id\":" + CJSONEntry::quoteValue(getSync().getClientID());
|
|
326
|
+
boolean bSend = false;
|
|
327
|
+
int i = 0;
|
|
328
|
+
|
|
329
|
+
getDB().Lock();
|
|
330
|
+
getDB().updateAllAttribChanges();
|
|
331
|
+
checkIgnorePushObjects();
|
|
332
|
+
if ( getSync().getSourceOptions().getBoolProperty(getID(), "full_update") )
|
|
333
|
+
getDB().updateFullUpdateChanges( getID() );
|
|
334
|
+
|
|
335
|
+
for( i = 0; i < 3; i++ )
|
|
336
|
+
{
|
|
337
|
+
String strBody1;
|
|
338
|
+
makePushBody_Ver3(strBody1, arUpdateTypes[i], true);
|
|
339
|
+
if (strBody1.length() > 0)
|
|
340
|
+
{
|
|
341
|
+
strBody += "," + strBody1;
|
|
342
|
+
|
|
343
|
+
String strBlobAttrs = "";
|
|
344
|
+
for ( int j = 0; j < (int)m_arBlobAttrs.size(); j++)
|
|
345
|
+
{
|
|
346
|
+
if ( strBlobAttrs.length() > 0 )
|
|
347
|
+
strBlobAttrs += ",";
|
|
348
|
+
|
|
349
|
+
strBlobAttrs += CJSONEntry::quoteValue(m_arBlobAttrs.elementAt(j));
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if ( strBlobAttrs.length() > 0 )
|
|
353
|
+
strBody += ",\"blob_fields\":[" + strBlobAttrs + "]";
|
|
354
|
+
|
|
355
|
+
arUpdateSent[i] = true;
|
|
356
|
+
bSend = true;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (!bSend)
|
|
361
|
+
{
|
|
362
|
+
//check for push_changes
|
|
363
|
+
IDBResult res = getDB().executeSQL("SELECT attrib_type FROM changed_values where source_id=? and update_type =?", getID(), "push_changes" );
|
|
364
|
+
bSend = !res.isEnd();
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
strBody += "}";
|
|
368
|
+
|
|
369
|
+
getDB().Unlock();
|
|
370
|
+
|
|
371
|
+
if ( bSend && getSync().isContinueSync())
|
|
372
|
+
{
|
|
373
|
+
LOG(INFO) + "Push client changes to server. Source: " + getName() + "Size :" + strBody.length();
|
|
374
|
+
if ( !RHOCONF().getBool("log_skip_post") )
|
|
375
|
+
LOG(TRACE) + "Push body: " + strBody;
|
|
376
|
+
|
|
377
|
+
if ( getSync().getSourceOptions().getBoolProperty(getID(), "set_sync_push_body" ) )
|
|
378
|
+
getSync().getSourceOptions().setProperty(getID(), "sync_push_body", strBody.c_str() );
|
|
379
|
+
|
|
380
|
+
if ( getSync().getSourceOptions().getIntProperty(getID(), "sync_push_error" ) > 0 )
|
|
381
|
+
{
|
|
382
|
+
m_nErrCode = getSync().getSourceOptions().getIntProperty(getID(), "sync_push_error" );
|
|
383
|
+
m_strError = getSync().getSourceOptions().getProperty(getID(), "sync_push_error_text" );
|
|
384
|
+
}else
|
|
385
|
+
{
|
|
386
|
+
Hashtable<String, String> reqHeaders;
|
|
387
|
+
reqHeaders.put(getProtocol().getClientIDHeader(), getSync().getClientID());
|
|
388
|
+
if ( m_arMultipartItems.size() > 0 )
|
|
389
|
+
{
|
|
390
|
+
CMultipartItem* pItem = new CMultipartItem();
|
|
391
|
+
CMultipartItem& oItem = *pItem;
|
|
392
|
+
oItem.m_strBody = strBody;
|
|
393
|
+
//oItem.m_strContentType = getProtocol().getContentType();
|
|
394
|
+
oItem.m_strName = "cud";
|
|
395
|
+
m_arMultipartItems.addElement(pItem);
|
|
396
|
+
|
|
397
|
+
NetResponse resp = getNet().pushMultipartData( getProtocol().getClientChangesUrl(getName()), m_arMultipartItems, &getSync(), &reqHeaders);
|
|
398
|
+
if ( !resp.isOK() )
|
|
399
|
+
{
|
|
400
|
+
//getSync().stopSync();
|
|
401
|
+
m_nErrCode = RhoAppAdapter.getErrorFromResponse(resp);
|
|
402
|
+
m_strError = resp.getCharData();
|
|
403
|
+
}
|
|
404
|
+
}else
|
|
405
|
+
{
|
|
406
|
+
NetResponse resp = getNet().doRequest("POST", getProtocol().getClientChangesUrl(getName()), strBody, &getSync(), &reqHeaders);
|
|
407
|
+
if ( !resp.isOK() )
|
|
408
|
+
{
|
|
409
|
+
//getSync().stopSync();
|
|
410
|
+
m_nErrCode = RhoAppAdapter.getErrorFromResponse(resp);
|
|
411
|
+
m_strError = resp.getCharData();
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
#ifndef RHO_NO_RUBY
|
|
417
|
+
if ( getSync().isNoThreadedMode() && getSync().getSourceOptions().getProperty(getID(), "sync_push_callback" ).length() > 0 )
|
|
418
|
+
rho_ruby_callmethod( getSync().getSourceOptions().getProperty(getID(), "sync_push_callback" ).c_str() );
|
|
419
|
+
#endif //RHO_NO_RUBY
|
|
420
|
+
|
|
421
|
+
getDB().Lock();
|
|
422
|
+
for( i = 0; i < 3; i++ )
|
|
423
|
+
{
|
|
424
|
+
if ( arUpdateSent[i] )
|
|
425
|
+
{
|
|
426
|
+
if ( m_nErrCode == RhoAppAdapter.ERR_NONE )
|
|
427
|
+
{
|
|
428
|
+
//oo conflicts
|
|
429
|
+
if ( i < 1 && !getSync().getSourceOptions().getBoolProperty(getID(), "pass_through") ) //create
|
|
430
|
+
getDB().executeSQL("UPDATE changed_values SET sent=2 WHERE source_id=? and update_type=? and sent=1", getID(), arUpdateTypes[i] );
|
|
431
|
+
else
|
|
432
|
+
//
|
|
433
|
+
getDB().executeSQL("DELETE FROM changed_values WHERE source_id=? and update_type=? and sent=1", getID(), arUpdateTypes[i] );
|
|
434
|
+
}else
|
|
435
|
+
{
|
|
436
|
+
if ( i == 0 ) //create
|
|
437
|
+
{
|
|
438
|
+
//remove deleted while sync objects
|
|
439
|
+
Hashtable<String,int> hashDeletes;
|
|
440
|
+
{
|
|
441
|
+
IDBResult res = getDB().executeSQL("SELECT distinct(object) FROM changed_values where source_id=? and update_type=? and sent=0", getID(), "delete" );
|
|
442
|
+
for( ; !res.isEnd(); res.next() )
|
|
443
|
+
hashDeletes.put( res.getStringByIdx(0), 1 );
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
Vector<String> arObjs;
|
|
447
|
+
IDBResult res = getDB().executeSQL("SELECT distinct(object) FROM changed_values where source_id=? and update_type=? and sent=1", getID(), arUpdateTypes[i] );
|
|
448
|
+
for( ; !res.isEnd(); res.next() )
|
|
449
|
+
arObjs.addElement( res.getStringByIdx(0) );
|
|
450
|
+
|
|
451
|
+
for ( int j = 0; j < (int)arObjs.size(); j++ )
|
|
452
|
+
{
|
|
453
|
+
if ( !hashDeletes.containsKey(arObjs[j]) )
|
|
454
|
+
getDB().executeSQL("INSERT INTO changed_values(update_type, attrib, source_id, object) VALUES(?,?,?,?)", arUpdateTypes[i], "object", getID(), arObjs[j] );
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
for ( int j = 0; j < (int)arObjs.size(); j++ )
|
|
458
|
+
getDB().executeSQL("DELETE FROM changed_values WHERE source_id=? and object=? and attrib<>?", getID(), arObjs[j], "object" );
|
|
459
|
+
|
|
460
|
+
}
|
|
461
|
+
else if ( i == 1 )//update
|
|
462
|
+
{
|
|
463
|
+
//remove updates with sent=1 if sent=0 exists
|
|
464
|
+
Vector<String> arObjs, arAttribs;
|
|
465
|
+
IDBResult res = getDB().executeSQL("SELECT object, attrib FROM changed_values where source_id=? and update_type=? and sent=0", getID(), arUpdateTypes[i] );
|
|
466
|
+
for( ; !res.isEnd(); res.next() )
|
|
467
|
+
{
|
|
468
|
+
arObjs.addElement( res.getStringByIdx(0) );
|
|
469
|
+
arAttribs.addElement( res.getStringByIdx(1) );
|
|
470
|
+
}
|
|
471
|
+
for ( int j = 0; j < (int)arObjs.size(); j++ )
|
|
472
|
+
{
|
|
473
|
+
getDB().executeSQL("DELETE FROM changed_values WHERE source_id=? and object=? and attrib=? and update_type = ? and sent=1", getID(), arObjs[j], arAttribs[j], arUpdateTypes[i] );
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
getDB().executeSQL("UPDATE changed_values SET sent=0 WHERE source_id=? and update_type=? and sent=1", getID(), arUpdateTypes[i] );
|
|
477
|
+
}
|
|
478
|
+
else
|
|
479
|
+
getDB().executeSQL("UPDATE changed_values SET sent=0 WHERE source_id=? and update_type=? and sent=1", getID(), arUpdateTypes[i] );
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
if (m_nErrCode == RhoAppAdapter.ERR_NONE)
|
|
485
|
+
getDB().executeSQL("DELETE FROM changed_values WHERE source_id=? and update_type=?", getID(), "push_changes" );
|
|
486
|
+
|
|
487
|
+
getDB().Unlock();
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
m_arMultipartItems.removeAllElements();
|
|
491
|
+
m_arBlobAttrs.removeAllElements();
|
|
492
|
+
}
|
|
493
|
+
/*
|
|
494
|
+
static void escapeDoubleQuotes(String& str)
|
|
495
|
+
{
|
|
496
|
+
const char* szQuote = strchr(str.c_str(), '\"');
|
|
497
|
+
while(szQuote)
|
|
498
|
+
{
|
|
499
|
+
int nPos = szQuote - str.c_str();
|
|
500
|
+
str.insert(nPos, 1, '\\');
|
|
501
|
+
if ( nPos+2 < str.length() )
|
|
502
|
+
szQuote = strchr(str.c_str()+nPos+2, '\"');
|
|
503
|
+
else
|
|
504
|
+
szQuote = 0;
|
|
505
|
+
}
|
|
506
|
+
}*/
|
|
507
|
+
|
|
508
|
+
//{"source_name":"SampleAdapter","client_id":1,"create":{"1":{"brand":"Apple","name":"iPhone","price":"199.99"}}}
|
|
509
|
+
//{"source_name":"SampleAdapter","client_id":1,"update":{"1":{"brand":"Apple","name":"iPhone","price":"199.99"}}}
|
|
510
|
+
//{"source_name":"SampleAdapter","client_id":1,"delete":{"1":{"brand":"Apple","name":"iPhone","price":"199.99"}}}
|
|
511
|
+
//{"source_name":"SampleAdapter","client_id":1,"delete":{"3":{"brand":"HTC","name":"Fuze","price":"299.99"}},"create":{"1":{"brand":"Apple","name":"iPhone","price":"199.99"}},"update":{"2":{"brand":"Android","name":"G2","price":"99.99"}}}
|
|
512
|
+
void CSyncSource::makePushBody_Ver3(String& strBody, const String& strUpdateType, boolean isSync)
|
|
513
|
+
{
|
|
514
|
+
getDB().Lock();
|
|
515
|
+
|
|
516
|
+
//if ( isSync )
|
|
517
|
+
// getDB().updateAllAttribChanges();
|
|
518
|
+
|
|
519
|
+
IDBResult res = getDB().executeSQL("SELECT attrib, object, value, attrib_type "
|
|
520
|
+
"FROM changed_values where source_id=? and update_type =? and sent<=1 ORDER BY object", getID(), strUpdateType.c_str() );
|
|
521
|
+
|
|
522
|
+
if ( res.isEnd() )
|
|
523
|
+
{
|
|
524
|
+
getDB().Unlock();
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
String strCurObject = "";
|
|
529
|
+
boolean bFirst = true;
|
|
530
|
+
for( ; !res.isEnd(); res.next() )
|
|
531
|
+
{
|
|
532
|
+
String strAttrib = res.getStringByIdx(0);
|
|
533
|
+
String strObject = res.getStringByIdx(1);
|
|
534
|
+
String value = res.getStringByIdx(2);
|
|
535
|
+
String attribType = res.getStringByIdx(3);
|
|
536
|
+
|
|
537
|
+
if ( m_hashIgnorePushObjects.containsKey(strObject) || strObject.length() == 0 )
|
|
538
|
+
continue;
|
|
539
|
+
|
|
540
|
+
if ( attribType.compare("blob.file") == 0 && value.length() > 0 )
|
|
541
|
+
{
|
|
542
|
+
CMultipartItem* pItem = new CMultipartItem();
|
|
543
|
+
CMultipartItem& oItem = *pItem;
|
|
544
|
+
oItem.m_strFilePath = RHODESAPPBASE().resolveDBFilesPath(value);
|
|
545
|
+
oItem.m_strContentType = "application/octet-stream";
|
|
546
|
+
oItem.m_strName = strAttrib + "-" + strObject;
|
|
547
|
+
|
|
548
|
+
if ( m_arBlobAttrs.indexOf(strAttrib) == -1 )
|
|
549
|
+
m_arBlobAttrs.addElement(strAttrib);
|
|
550
|
+
|
|
551
|
+
m_arMultipartItems.addElement(pItem);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
if ( strBody.length() == 0 )
|
|
555
|
+
{
|
|
556
|
+
if ( !isSync )
|
|
557
|
+
strBody += "{";
|
|
558
|
+
else
|
|
559
|
+
strBody += "\"" + strUpdateType + "\":{";
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
if ( strObject.compare(strCurObject) != 0 )
|
|
563
|
+
{
|
|
564
|
+
if ( strCurObject.length() > 0 )
|
|
565
|
+
{
|
|
566
|
+
if ( !bFirst )
|
|
567
|
+
strBody += "}";
|
|
568
|
+
strBody += ",";
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
bFirst = true;
|
|
572
|
+
strBody += CJSONEntry::quoteValue(strObject);
|
|
573
|
+
strCurObject = strObject;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
if (!bFirst)
|
|
577
|
+
strBody += ",";
|
|
578
|
+
|
|
579
|
+
if ( strAttrib.length() > 0 )
|
|
580
|
+
{
|
|
581
|
+
if ( bFirst )
|
|
582
|
+
strBody += ":{";
|
|
583
|
+
|
|
584
|
+
strBody += CJSONEntry::quoteValue(strAttrib) + ":" + CJSONEntry::quoteValue(value);
|
|
585
|
+
bFirst = false;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
if ( strBody.length() > 0 )
|
|
590
|
+
{
|
|
591
|
+
if ( !bFirst )
|
|
592
|
+
strBody += "}";
|
|
593
|
+
|
|
594
|
+
strBody += "}";
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if ( isSync )
|
|
598
|
+
getDB().executeSQL("UPDATE changed_values SET sent=1 WHERE source_id=? and update_type=? and sent=0", getID(), strUpdateType.c_str() );
|
|
599
|
+
|
|
600
|
+
getDB().Unlock();
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
void CSyncSource::applyChangedValues()
|
|
604
|
+
{
|
|
605
|
+
String strBody = "";
|
|
606
|
+
makePushBody_Ver3(strBody, "create", false);
|
|
607
|
+
if ( strBody.length() > 0 )
|
|
608
|
+
{
|
|
609
|
+
CJSONEntry oEntry(strBody.c_str());
|
|
610
|
+
processSyncCommand("insert", oEntry, false );
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
strBody = "";
|
|
614
|
+
makePushBody_Ver3(strBody, "delete", false);
|
|
615
|
+
if ( strBody.length() > 0 )
|
|
616
|
+
{
|
|
617
|
+
CJSONEntry oEntry(strBody.c_str());
|
|
618
|
+
processSyncCommand("delete", oEntry, false );
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
strBody = "";
|
|
622
|
+
makePushBody_Ver3(strBody, "update", false);
|
|
623
|
+
if ( strBody.length() > 0 )
|
|
624
|
+
{
|
|
625
|
+
CJSONEntry oEntry(strBody.c_str());
|
|
626
|
+
processSyncCommand("insert", oEntry, false );
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
void CSyncSource::syncServerChanges()
|
|
631
|
+
{
|
|
632
|
+
LOG(INFO) + "Sync server changes source ID :" + getID();
|
|
633
|
+
|
|
634
|
+
while( getSync().isContinueSync() &&
|
|
635
|
+
( m_nErrCode == RhoAppAdapter.ERR_NONE || m_nErrCode == RhoAppAdapter.ERR_CUSTOMSYNCSERVER) )
|
|
636
|
+
{
|
|
637
|
+
setCurPageCount(0);
|
|
638
|
+
String strUrl = getProtocol().getServerQueryUrl(getName(), getSync().getClientID(), getSync().getSyncPageSize());
|
|
639
|
+
Hashtable<String, String> reqHeaders;
|
|
640
|
+
reqHeaders.put(getProtocol().getClientIDHeader(), getSync().getClientID());
|
|
641
|
+
|
|
642
|
+
if ( !m_bTokenFromDB && getToken() > 1 )
|
|
643
|
+
strUrl += "&token=" + convertToStringA(getToken());
|
|
644
|
+
|
|
645
|
+
if ( m_strQueryParams.length() > 0 )
|
|
646
|
+
strUrl += "&" + m_strQueryParams;
|
|
647
|
+
|
|
648
|
+
LOG(INFO) + "Pull changes from server. Url: " + strUrl;
|
|
649
|
+
PROF_START("Net");
|
|
650
|
+
NetResponse resp = getNet().doRequest("GET", strUrl, "", &getSync(), &reqHeaders);
|
|
651
|
+
PROF_STOP("Net");
|
|
652
|
+
|
|
653
|
+
if ( !resp.isOK() )
|
|
654
|
+
{
|
|
655
|
+
//getSync().stopSync();
|
|
656
|
+
m_nErrCode = RhoAppAdapter.getErrorFromResponse(resp);
|
|
657
|
+
m_strError = resp.getCharData();
|
|
658
|
+
continue;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
const char* szData = null;
|
|
662
|
+
String strTestResp = getSync().getSourceOptions().getProperty(getID(), "rho_server_response");
|
|
663
|
+
if ( strTestResp.length() > 0 )
|
|
664
|
+
{
|
|
665
|
+
szData = strTestResp.c_str();
|
|
666
|
+
getNotify().setFakeServerResponse(true);
|
|
667
|
+
}
|
|
668
|
+
else
|
|
669
|
+
szData = resp.getCharData();
|
|
670
|
+
|
|
671
|
+
//LOG(INFO) + szData;
|
|
672
|
+
PROF_START("Parse");
|
|
673
|
+
CJSONArrayIterator oJsonArr(szData);
|
|
674
|
+
PROF_STOP("Parse");
|
|
675
|
+
|
|
676
|
+
processServerResponse_ver3(oJsonArr);
|
|
677
|
+
|
|
678
|
+
if (getSync().getSourceOptions().getBoolProperty(getID(), "pass_through"))
|
|
679
|
+
processToken(0);
|
|
680
|
+
|
|
681
|
+
if ( getToken() == 0 )
|
|
682
|
+
break;
|
|
683
|
+
|
|
684
|
+
if ( strTestResp.length() > 0 )
|
|
685
|
+
break;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
if ( getSync().isSchemaChanged() )
|
|
689
|
+
getSync().stopSync();
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
//{"create-error":{"0_broken_object_id":{"name":"wrongname","an_attribute":"error create"},"0_broken_object_id-error":{"message":"error create"}}}
|
|
693
|
+
void CSyncSource::processServerErrors(CJSONEntry& oCmds)
|
|
694
|
+
{
|
|
695
|
+
Hashtable<String, String> errors;
|
|
696
|
+
|
|
697
|
+
const char* arErrTypes[] = {"source-error", "search-error", "create-error", "update-error", "delete-error", "update-rollback", null};
|
|
698
|
+
for( int i = 0; ; i++ )
|
|
699
|
+
{
|
|
700
|
+
if ( arErrTypes[i] == null )
|
|
701
|
+
break;
|
|
702
|
+
if ( !oCmds.hasName(arErrTypes[i]) )
|
|
703
|
+
continue;
|
|
704
|
+
|
|
705
|
+
String strServerError = "";
|
|
706
|
+
|
|
707
|
+
CJSONEntry errSrc = oCmds.getEntry(arErrTypes[i]);
|
|
708
|
+
|
|
709
|
+
String errorType = "";
|
|
710
|
+
CJSONStructIterator errIter(errSrc);
|
|
711
|
+
|
|
712
|
+
if ( i == 0 || i == 1 )//"source-error", "search-error"
|
|
713
|
+
{
|
|
714
|
+
if ( errIter.getCurValue().hasName("message") ) {
|
|
715
|
+
errorType = errIter.getCurKey() + "-json";
|
|
716
|
+
strServerError = String("{\"message\":\"")+errIter.getCurValue().getString("message")+"\"}";
|
|
717
|
+
}
|
|
718
|
+
} else {
|
|
719
|
+
//"create-error", "update-error", "delete-error", "update-rollback"
|
|
720
|
+
errorType = String(arErrTypes[i]) + "-json";
|
|
721
|
+
|
|
722
|
+
Hashtable<String,String> objErrors;
|
|
723
|
+
|
|
724
|
+
//iterate objects
|
|
725
|
+
for( ; !errIter.isEnd(); errIter.next() )
|
|
726
|
+
{
|
|
727
|
+
String strObject = errIter.getCurKey();
|
|
728
|
+
|
|
729
|
+
if ( String_endsWith(strObject, "-error") )
|
|
730
|
+
{
|
|
731
|
+
strObject = strObject.substr(0, strObject.length()-6);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
String strValue = objErrors.get(strObject);
|
|
735
|
+
|
|
736
|
+
if ( strValue.length() == 0 ) {
|
|
737
|
+
strValue = "{";
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
if ( String_endsWith(strValue, "}") ) {
|
|
741
|
+
strValue = strValue.substr(0,strValue.length()-1);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
if ( errIter.getCurValue().hasName("message") )
|
|
745
|
+
{
|
|
746
|
+
if (strValue.length() > 1) {
|
|
747
|
+
strValue += ",";
|
|
748
|
+
}
|
|
749
|
+
strValue += String("\"message\":\"") + errIter.getCurValue().getString("message") + "\"";
|
|
750
|
+
} else {
|
|
751
|
+
CJSONStructIterator attrIter(errIter.getCurValue());
|
|
752
|
+
bool first = true;
|
|
753
|
+
String strAttrs = "";
|
|
754
|
+
if ( !attrIter.isEnd() ) {
|
|
755
|
+
strAttrs += "\"attributes\":{";
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
for( ; !attrIter.isEnd(); attrIter.next() ) {
|
|
759
|
+
if ( first ) {
|
|
760
|
+
first = false;
|
|
761
|
+
} else {
|
|
762
|
+
strAttrs += ",";
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
String strAttrName = attrIter.getCurKey();
|
|
766
|
+
String strAttrValue = attrIter.getCurString();
|
|
767
|
+
|
|
768
|
+
strAttrs += "\""+strAttrName+"\":\""+strAttrValue+"\"";
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
if ( strAttrs.length() > 0 ) {
|
|
772
|
+
strAttrs += "}";
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
if ( strValue.length() > 1 ) {
|
|
776
|
+
strValue += ",";
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
strValue += strAttrs;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
strValue += "}";
|
|
783
|
+
|
|
784
|
+
objErrors.put(strObject,strValue);
|
|
785
|
+
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
if ( objErrors.size() > 0 ) {
|
|
789
|
+
rho::String strObjects = "";
|
|
790
|
+
for ( Hashtable<String,String>::const_iterator it = objErrors.begin(); it != objErrors.end(); ++it ) {
|
|
791
|
+
if ( strObjects.size() > 0 ) {
|
|
792
|
+
strObjects += ",";
|
|
793
|
+
}
|
|
794
|
+
strObjects += "\"" + it->first + "\":" + it->second;
|
|
795
|
+
}
|
|
796
|
+
strServerError = rho::String("{") + strObjects + "}";
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
if ( (errorType.length()>0) && (strServerError.size()>0) ) {
|
|
802
|
+
errors.put(errorType,strServerError);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
if ( errors.size() > 0 ) {
|
|
809
|
+
getNotify().fireSyncNotification2(this, true, RhoAppAdapter.ERR_CUSTOMSYNCSERVER, errors);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
void CSyncSource::processServerResponse_ver3(CJSONArrayIterator& oJsonArr, bool isRecoveryMode )
|
|
814
|
+
{
|
|
815
|
+
PROF_START("Data1");
|
|
816
|
+
|
|
817
|
+
if ( oJsonArr.isEnd() )
|
|
818
|
+
{
|
|
819
|
+
getSync().stopSync();
|
|
820
|
+
m_nErrCode = RhoAppAdapter.ERR_UNEXPECTEDSERVERRESPONSE;
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
int nVersion = 0;
|
|
825
|
+
if ( !oJsonArr.isEnd() && oJsonArr.getCurItem().hasName("version") )
|
|
826
|
+
{
|
|
827
|
+
nVersion = oJsonArr.getCurItem().getInt("version");
|
|
828
|
+
oJsonArr.next();
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
if ( nVersion != getProtocol().getVersion() )
|
|
832
|
+
{
|
|
833
|
+
LOG(ERROR) + "Sync server send data with incompatible version. Client version: " + convertToStringA(getProtocol().getVersion()) +
|
|
834
|
+
"; Server response version: " + convertToStringA(nVersion) + ". Source name: " + getName();
|
|
835
|
+
getSync().stopSync();
|
|
836
|
+
m_nErrCode = RhoAppAdapter.ERR_SYNCVERSION;
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
if ( !oJsonArr.isEnd() && oJsonArr.getCurItem().hasName("token"))
|
|
841
|
+
{
|
|
842
|
+
processToken(oJsonArr.getCurItem().getUInt64("token"));
|
|
843
|
+
oJsonArr.next();
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
if ( !oJsonArr.isEnd() && oJsonArr.getCurItem().hasName("source") )
|
|
847
|
+
{
|
|
848
|
+
//skip it. it uses in search only
|
|
849
|
+
oJsonArr.next();
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
if ( !oJsonArr.isEnd() && oJsonArr.getCurItem().hasName("count") )
|
|
853
|
+
{
|
|
854
|
+
setCurPageCount(oJsonArr.getCurItem().getInt("count"));
|
|
855
|
+
oJsonArr.next();
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
if ( !oJsonArr.isEnd() && oJsonArr.getCurItem().hasName("refresh_time") )
|
|
859
|
+
{
|
|
860
|
+
setRefreshTime(oJsonArr.getCurItem().getInt("refresh_time"));
|
|
861
|
+
oJsonArr.next();
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
if ( !oJsonArr.isEnd() && oJsonArr.getCurItem().hasName("progress_count") )
|
|
865
|
+
{
|
|
866
|
+
//TODO: progress_count
|
|
867
|
+
//setTotalCount(oJsonArr.getCurItem().getInt("progress_count"));
|
|
868
|
+
oJsonArr.next();
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
if ( !oJsonArr.isEnd() && oJsonArr.getCurItem().hasName("total_count") )
|
|
872
|
+
{
|
|
873
|
+
setTotalCount(oJsonArr.getCurItem().getInt("total_count"));
|
|
874
|
+
oJsonArr.next();
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
//if ( getServerObjectsCount() == 0 )
|
|
878
|
+
// getNotify().fireSyncNotification(this, false, RhoAppAdapter.ERR_NONE, "");
|
|
879
|
+
|
|
880
|
+
if ( getToken() == 0 )
|
|
881
|
+
{
|
|
882
|
+
//oo conflicts
|
|
883
|
+
getDB().executeSQL("DELETE FROM changed_values where source_id=? and sent>=3", getID() );
|
|
884
|
+
//
|
|
885
|
+
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
LOG(INFO) + "Got " + getCurPageCount() + "(Processed: " + getServerObjectsCount() + ") records of " + getTotalCount() + " from server. Source: " + getName()
|
|
889
|
+
+ ". Version: " + nVersion;
|
|
890
|
+
|
|
891
|
+
PROF_STOP("Data1");
|
|
892
|
+
if ( !oJsonArr.isEnd() && getSync().isContinueSync() )
|
|
893
|
+
{
|
|
894
|
+
CJSONEntry oCmds = oJsonArr.getCurItem();
|
|
895
|
+
PROF_START("Data");
|
|
896
|
+
//TODO: use isUIWaitDB inside processSyncCommand
|
|
897
|
+
// if ( getDB().isUIWaitDB() )
|
|
898
|
+
// {
|
|
899
|
+
// LOG(INFO) + "Commit transaction because of UI request.";
|
|
900
|
+
// getDB().endTransaction();
|
|
901
|
+
// getDB().startTransaction();
|
|
902
|
+
// }
|
|
903
|
+
|
|
904
|
+
if ( oCmds.hasName("schema-changed") )
|
|
905
|
+
{
|
|
906
|
+
getSync().setSchemaChanged(true);
|
|
907
|
+
}else
|
|
908
|
+
{
|
|
909
|
+
processServerErrors(oCmds);
|
|
910
|
+
|
|
911
|
+
getDB().startTransaction();
|
|
912
|
+
|
|
913
|
+
LOG(INFO) + "SyncSource: pass_through = " + getSync().getSourceOptions().getBoolProperty(getID(), "pass_through");
|
|
914
|
+
if (getSync().getSourceOptions().getBoolProperty(getID(), "pass_through"))
|
|
915
|
+
{
|
|
916
|
+
if ( m_bSchemaSource )
|
|
917
|
+
getDB().executeSQL( (String("DELETE FROM ") + getName()).c_str() );
|
|
918
|
+
else
|
|
919
|
+
getDB().executeSQL("DELETE FROM object_values WHERE source_id=?", getID() );
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
if ( oCmds.hasName("metadata") && getSync().isContinueSync() )
|
|
923
|
+
{
|
|
924
|
+
String strMetadata = oCmds.getString("metadata");
|
|
925
|
+
getDB().executeSQL("UPDATE sources SET metadata=? WHERE source_id=?", strMetadata, getID() );
|
|
926
|
+
}
|
|
927
|
+
if ( oCmds.hasName("links") && getSync().isContinueSync() )
|
|
928
|
+
processSyncCommand("links", oCmds.getEntry("links"), true );
|
|
929
|
+
if ( oCmds.hasName("delete") && getSync().isContinueSync() )
|
|
930
|
+
processSyncCommand("delete", oCmds.getEntry("delete"), true );
|
|
931
|
+
if ( oCmds.hasName("insert") && getSync().isContinueSync() )
|
|
932
|
+
processSyncCommand("insert", oCmds.getEntry("insert"), true );
|
|
933
|
+
|
|
934
|
+
PROF_STOP("Data");
|
|
935
|
+
|
|
936
|
+
PROF_START("DB");
|
|
937
|
+
getDB().endTransaction();
|
|
938
|
+
PROF_STOP("DB");
|
|
939
|
+
|
|
940
|
+
if (!isRecoveryMode) {
|
|
941
|
+
getNotify().fireObjectsNotification();
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
PROF_START("Data1");
|
|
947
|
+
if ( getCurPageCount() > 0 ) {
|
|
948
|
+
if ( !isRecoveryMode ) {
|
|
949
|
+
getNotify().fireSyncNotification(this, false, RhoAppAdapter.ERR_NONE, "");
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
PROF_STOP("Data1");
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
int CSyncSource::propertyBagInsertAndUpdate(const String& tableName, const String& to, json::CJSONEntry oCmdEntry, boolean bCheckUIRequest, rho::Hashtable<String, bool>& changedObjects)
|
|
957
|
+
{
|
|
958
|
+
// parse freesed props
|
|
959
|
+
rho::Hashtable<String, bool> freezedProps;
|
|
960
|
+
makeFreezedPropsHash(freezedProps);
|
|
961
|
+
|
|
962
|
+
bool should_check_props = bCheckUIRequest && (freezedProps.size() > 0);
|
|
963
|
+
|
|
964
|
+
// create temp table for inserting new data
|
|
965
|
+
getDB().executeSQL((String("DROP TABLE IF EXISTS ") + tableName).c_str());
|
|
966
|
+
getDB().executeSQL((String("CREATE TEMP TABLE ") + tableName + " ( "
|
|
967
|
+
"\"source_id\" BIGINT default NULL, "
|
|
968
|
+
"\"attrib\" varchar(255) default NULL, "
|
|
969
|
+
"\"object\" varchar(255) default NULL, "
|
|
970
|
+
"\"value\" varchar default NULL);").c_str());
|
|
971
|
+
|
|
972
|
+
// fill data using server JSON reply
|
|
973
|
+
CJSONStructIterator objIter(oCmdEntry);
|
|
974
|
+
int inserted = 0;
|
|
975
|
+
for( ; !objIter.isEnd() && getSync().isContinueSync(); objIter.next() )
|
|
976
|
+
{
|
|
977
|
+
String strObject = objIter.getCurKey();
|
|
978
|
+
CJSONStructIterator attrIter( objIter.getCurValue() );
|
|
979
|
+
|
|
980
|
+
bool was_changed = false;
|
|
981
|
+
|
|
982
|
+
for( ; !attrIter.isEnd(); attrIter.next() )
|
|
983
|
+
{
|
|
984
|
+
CAttrValue oAttrValue(attrIter.getCurKey(),attrIter.getCurString());
|
|
985
|
+
|
|
986
|
+
if ( should_check_props && !freezedProps.containsKey(oAttrValue.m_strAttrib)) {
|
|
987
|
+
LOG(INFO) + "Skip Non-exist property : " + oAttrValue.m_strAttrib + ". For model : " + getName();
|
|
988
|
+
continue;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
if ( !processBlob("insert",strObject,oAttrValue) )
|
|
992
|
+
continue;
|
|
993
|
+
|
|
994
|
+
getDB().executeSQL((String("INSERT INTO ") + tableName +
|
|
995
|
+
"(attrib, source_id, object, value) VALUES(?,?,?,?)").c_str(),
|
|
996
|
+
oAttrValue.m_strAttrib, getID(), strObject, oAttrValue.m_strValue );
|
|
997
|
+
|
|
998
|
+
++inserted;
|
|
999
|
+
|
|
1000
|
+
was_changed = true;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
if (was_changed)
|
|
1004
|
+
{
|
|
1005
|
+
changedObjects[strObject] = true;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
// index changes
|
|
1009
|
+
getDB().executeSQL((String("CREATE UNIQUE INDEX idx_") + tableName + " ON " + tableName + "(\"object\", \"attrib\", \"source_id\");").c_str());
|
|
1010
|
+
|
|
1011
|
+
// find conflicts when source_id, object and attrib are same but values differ
|
|
1012
|
+
IDBResult conflicts = getDB().executeSQL(
|
|
1013
|
+
(String("SELECT ") +
|
|
1014
|
+
tableName+".value, " + tableName+".object, "+ tableName + ".attrib, " + tableName + ".source_id "
|
|
1015
|
+
" FROM "+tableName+" , " + to +
|
|
1016
|
+
" WHERE " +
|
|
1017
|
+
to+".source_id="+tableName+".source_id AND " +
|
|
1018
|
+
to+".object="+tableName+".object AND " +
|
|
1019
|
+
to+".attrib="+tableName+".attrib AND " +
|
|
1020
|
+
to+".value!="+tableName+".value;").c_str());
|
|
1021
|
+
|
|
1022
|
+
// writeback conflicts
|
|
1023
|
+
while (!conflicts.isEnd())
|
|
1024
|
+
{
|
|
1025
|
+
if ( getSyncType().compare("none") != 0 )
|
|
1026
|
+
{
|
|
1027
|
+
// oo conflicts
|
|
1028
|
+
getDB().executeSQL("UPDATE changed_values SET sent=4 where object=? and attrib=? and source_id=? and update_type=? and sent>1",
|
|
1029
|
+
conflicts.getStringByIdx(1), conflicts.getStringByIdx(2), conflicts.getIntByIdx(3), "create" );
|
|
1030
|
+
//
|
|
1031
|
+
}
|
|
1032
|
+
conflicts.next();
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
// update destination table
|
|
1036
|
+
IDBResult res = getDB().executeSQL((String("INSERT OR REPLACE INTO ") + to + " SELECT * FROM " + tableName).c_str());
|
|
1037
|
+
|
|
1038
|
+
getDB().executeSQL((String("DROP TABLE ") + tableName).c_str());
|
|
1039
|
+
|
|
1040
|
+
if ( getSyncType().compare("none") != 0 )
|
|
1041
|
+
{
|
|
1042
|
+
for(rho::Hashtable<String, bool>::const_iterator iter = changedObjects.begin(); iter!=changedObjects.end(); ++iter)
|
|
1043
|
+
{
|
|
1044
|
+
getNotify().onObjectChanged(getID(),iter->first, CSyncNotify::enUpdate);
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
m_nInserted += inserted;
|
|
1049
|
+
|
|
1050
|
+
return inserted;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
void CSyncSource::processSyncCommand(const String& strCmd, CJSONEntry oCmdEntry, boolean bCheckUIRequest)
|
|
1054
|
+
{
|
|
1055
|
+
CJSONStructIterator objIter(oCmdEntry);
|
|
1056
|
+
|
|
1057
|
+
if ( m_bSchemaSource ) {
|
|
1058
|
+
for( ; !objIter.isEnd() && getSync().isContinueSync(); objIter.next() )
|
|
1059
|
+
{
|
|
1060
|
+
String strObject = objIter.getCurKey();
|
|
1061
|
+
CJSONStructIterator attrIter( objIter.getCurValue() );
|
|
1062
|
+
|
|
1063
|
+
processServerCmd_Ver3_Schema(strCmd,strObject,attrIter,bCheckUIRequest);
|
|
1064
|
+
|
|
1065
|
+
if ( getSyncType().compare("none") == 0 )
|
|
1066
|
+
continue;
|
|
1067
|
+
|
|
1068
|
+
if ( bCheckUIRequest )
|
|
1069
|
+
{
|
|
1070
|
+
if ( getDB().isUIWaitDB() )
|
|
1071
|
+
{
|
|
1072
|
+
LOG(INFO) + "Commit transaction because of UI request.";
|
|
1073
|
+
getDB().endTransaction();
|
|
1074
|
+
|
|
1075
|
+
checkProgressStepNotify(false);
|
|
1076
|
+
|
|
1077
|
+
CSyncThread::getInstance()->sleep(1000);
|
|
1078
|
+
getDB().startTransaction();
|
|
1079
|
+
}else
|
|
1080
|
+
checkProgressStepNotify(true);
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
} else {
|
|
1085
|
+
if (strCmd == "insert")
|
|
1086
|
+
{
|
|
1087
|
+
// batch insertions
|
|
1088
|
+
rho::Hashtable<String, bool> changedObjects;
|
|
1089
|
+
propertyBagInsertAndUpdate("temp_insert", "object_values", oCmdEntry, bCheckUIRequest, changedObjects);
|
|
1090
|
+
|
|
1091
|
+
} else {
|
|
1092
|
+
for( ; !objIter.isEnd() && getSync().isContinueSync(); objIter.next() )
|
|
1093
|
+
{
|
|
1094
|
+
String strObject = objIter.getCurKey();
|
|
1095
|
+
CJSONStructIterator attrIter( objIter.getCurValue() );
|
|
1096
|
+
|
|
1097
|
+
for( ; !attrIter.isEnd(); attrIter.next() )
|
|
1098
|
+
{
|
|
1099
|
+
String strAttrib = attrIter.getCurKey();
|
|
1100
|
+
String strValue = attrIter.getCurString();
|
|
1101
|
+
|
|
1102
|
+
processServerCmd_Ver3(strCmd,strObject,strAttrib,strValue,bCheckUIRequest);
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
if ( getSyncType().compare("none") == 0 )
|
|
1106
|
+
continue;
|
|
1107
|
+
|
|
1108
|
+
if ( bCheckUIRequest )
|
|
1109
|
+
{
|
|
1110
|
+
if ( getDB().isUIWaitDB() )
|
|
1111
|
+
{
|
|
1112
|
+
LOG(INFO) + "Commit transaction because of UI request.";
|
|
1113
|
+
getDB().endTransaction();
|
|
1114
|
+
|
|
1115
|
+
checkProgressStepNotify(false);
|
|
1116
|
+
|
|
1117
|
+
CSyncThread::getInstance()->sleep(1000);
|
|
1118
|
+
getDB().startTransaction();
|
|
1119
|
+
}
|
|
1120
|
+
else
|
|
1121
|
+
checkProgressStepNotify(true);
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
void CSyncSource::checkProgressStepNotify(boolean bEndTransaction)
|
|
1129
|
+
{
|
|
1130
|
+
int nSyncObjectCount = getNotify().incLastSyncObjectCount(getID());
|
|
1131
|
+
if ( getProgressStep() > 0 && (nSyncObjectCount%getProgressStep() == 0) )
|
|
1132
|
+
{
|
|
1133
|
+
if ( bEndTransaction )
|
|
1134
|
+
{
|
|
1135
|
+
LOG(INFO) + "Commit transaction because of Sync Progress notification.";
|
|
1136
|
+
getDB().endTransaction();
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
getNotify().fireSyncNotification(this, false, RhoAppAdapter.ERR_NONE, "");
|
|
1140
|
+
|
|
1141
|
+
if ( bEndTransaction )
|
|
1142
|
+
getDB().startTransaction();
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
void CSyncSource::processAssociations(const String& strOldObject, const String& strNewObject)
|
|
1147
|
+
{
|
|
1148
|
+
for ( int i = 0; i < (int)m_arAssociations.size(); i++ )
|
|
1149
|
+
{
|
|
1150
|
+
CSyncSource* pSrc = getSync().findSourceByName(m_arAssociations.elementAt(i).m_strSrcName);
|
|
1151
|
+
if ( pSrc != null )
|
|
1152
|
+
pSrc->updateAssociation(strOldObject, strNewObject, m_arAssociations.elementAt(i).m_strAttrib);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
void CSyncSource::updateAssociation(const String& strOldObject, const String& strNewObject, const String& strAttrib)
|
|
1157
|
+
{
|
|
1158
|
+
if ( m_bSchemaSource )
|
|
1159
|
+
{
|
|
1160
|
+
String strSqlUpdate = "UPDATE ";
|
|
1161
|
+
strSqlUpdate += getName() + " SET " + strAttrib + "=? where " + strAttrib + "=?";
|
|
1162
|
+
|
|
1163
|
+
getDB().executeSQL(strSqlUpdate.c_str(), strNewObject, strOldObject );
|
|
1164
|
+
}
|
|
1165
|
+
else
|
|
1166
|
+
getDB().executeSQL("UPDATE object_values SET value=? where attrib=? and source_id=? and value=?",
|
|
1167
|
+
strNewObject, strAttrib, getID(), strOldObject );
|
|
1168
|
+
|
|
1169
|
+
getDB().executeSQL("UPDATE changed_values SET value=? where attrib=? and source_id=? and value=?",
|
|
1170
|
+
strNewObject, strAttrib, getID(), strOldObject );
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
void CSyncSource::processServerCmd_Ver3_Schema(const String& strCmd, const String& strObject, CJSONStructIterator& attrIter, boolean bCheckUIRequest)//throws Exception
|
|
1174
|
+
{
|
|
1175
|
+
if ( strCmd.compare("insert") == 0 )
|
|
1176
|
+
{
|
|
1177
|
+
Vector<String> vecValues, vecAttrs;
|
|
1178
|
+
String strCols = "", strQuest = "", strSet = "";
|
|
1179
|
+
for( ; !attrIter.isEnd(); attrIter.next() )
|
|
1180
|
+
{
|
|
1181
|
+
CAttrValue oAttrValue(attrIter.getCurKey(),attrIter.getCurString());
|
|
1182
|
+
|
|
1183
|
+
if ( bCheckUIRequest && !checkFreezedProps(oAttrValue.m_strAttrib))
|
|
1184
|
+
continue;
|
|
1185
|
+
|
|
1186
|
+
if ( !processBlob(strCmd,strObject,oAttrValue) )
|
|
1187
|
+
break;
|
|
1188
|
+
|
|
1189
|
+
if ( strCols.length() > 0 )
|
|
1190
|
+
strCols += ",";
|
|
1191
|
+
if ( strQuest.length() > 0)
|
|
1192
|
+
strQuest += ",";
|
|
1193
|
+
if ( strSet.length() > 0)
|
|
1194
|
+
strSet += ",";
|
|
1195
|
+
|
|
1196
|
+
strCols += oAttrValue.m_strAttrib;
|
|
1197
|
+
strQuest += "?";
|
|
1198
|
+
strSet += oAttrValue.m_strAttrib + "=?";
|
|
1199
|
+
vecAttrs.addElement(oAttrValue.m_strAttrib);
|
|
1200
|
+
vecValues.addElement(oAttrValue.m_strValue);
|
|
1201
|
+
}
|
|
1202
|
+
vecValues.addElement(strObject);
|
|
1203
|
+
if ( strCols.length() > 0 )
|
|
1204
|
+
strCols += ",";
|
|
1205
|
+
if ( strQuest.length() > 0)
|
|
1206
|
+
strQuest += ",";
|
|
1207
|
+
|
|
1208
|
+
strCols += "object";
|
|
1209
|
+
strQuest += "?";
|
|
1210
|
+
|
|
1211
|
+
String strSqlInsert = "INSERT INTO ";
|
|
1212
|
+
strSqlInsert += getName() + " (";
|
|
1213
|
+
strSqlInsert += strCols + ") VALUES(" + strQuest + ")";
|
|
1214
|
+
|
|
1215
|
+
if ( !getSync().isContinueSync() )
|
|
1216
|
+
return;
|
|
1217
|
+
|
|
1218
|
+
IDBResult resInsert = getDB().executeSQLReportNonUniqueEx(strSqlInsert.c_str(), vecValues );
|
|
1219
|
+
if ( resInsert.isNonUnique() )
|
|
1220
|
+
{
|
|
1221
|
+
String strSqlUpdate = "UPDATE ";
|
|
1222
|
+
strSqlUpdate += getName() + " SET " + strSet + " WHERE object=?";
|
|
1223
|
+
getDB().executeSQLEx(strSqlUpdate.c_str(), vecValues);
|
|
1224
|
+
|
|
1225
|
+
if ( getSyncType().compare("none") != 0 )
|
|
1226
|
+
{
|
|
1227
|
+
// oo conflicts
|
|
1228
|
+
for( int i = 0; i < (int)vecAttrs.size(); i++ )
|
|
1229
|
+
{
|
|
1230
|
+
getDB().executeSQL("UPDATE changed_values SET sent=4 where object=? and attrib=? and source_id=? and update_type=? and sent>1",
|
|
1231
|
+
strObject, vecAttrs.elementAt(i), getID(), "create" );
|
|
1232
|
+
}
|
|
1233
|
+
//
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
if ( getSyncType().compare("none") != 0 )
|
|
1238
|
+
getNotify().onObjectChanged(getID(),strObject, CSyncNotify::enUpdate);
|
|
1239
|
+
|
|
1240
|
+
m_nInserted++;
|
|
1241
|
+
}else if (strCmd.compare("delete") == 0)
|
|
1242
|
+
{
|
|
1243
|
+
Vector<String> vecAttrs;
|
|
1244
|
+
String strSet = "";
|
|
1245
|
+
for( ; !attrIter.isEnd() && getSync().isContinueSync(); attrIter.next() )
|
|
1246
|
+
{
|
|
1247
|
+
CAttrValue oAttrValue(attrIter.getCurKey(),attrIter.getCurString());
|
|
1248
|
+
|
|
1249
|
+
if ( strSet.length() > 0 )
|
|
1250
|
+
strSet += ",";
|
|
1251
|
+
|
|
1252
|
+
vecAttrs.addElement(oAttrValue.m_strAttrib);
|
|
1253
|
+
strSet += oAttrValue.m_strAttrib + "=NULL";
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
String strSqlUpdate = "UPDATE ";
|
|
1257
|
+
strSqlUpdate += getName() + " SET " + strSet + " WHERE object=?";
|
|
1258
|
+
|
|
1259
|
+
if ( strSet.length() == 0 )
|
|
1260
|
+
return;
|
|
1261
|
+
|
|
1262
|
+
getDB().executeSQL(strSqlUpdate.c_str(), strObject);
|
|
1263
|
+
//Remove item if all nulls
|
|
1264
|
+
String strSelect = String("SELECT * FROM ") + getName() + " WHERE object=?";
|
|
1265
|
+
IDBResult res = getDB().executeSQL( strSelect.c_str(), strObject );
|
|
1266
|
+
if ( !res.isEnd() )
|
|
1267
|
+
{
|
|
1268
|
+
boolean bAllNulls = true;
|
|
1269
|
+
for( int i = 0; i < res.getColCount(); i ++)
|
|
1270
|
+
{
|
|
1271
|
+
if ( !res.isNullByIdx(i) && res.getColName(i).compare("object")!=0 )
|
|
1272
|
+
{
|
|
1273
|
+
bAllNulls = false;
|
|
1274
|
+
break;
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
if (bAllNulls)
|
|
1279
|
+
{
|
|
1280
|
+
String strDelete = String("DELETE FROM ") + getName() + " WHERE object=?";
|
|
1281
|
+
getDB().executeSQL( strDelete.c_str(), strObject);
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
if ( getSyncType().compare("none") != 0 )
|
|
1286
|
+
{
|
|
1287
|
+
getNotify().onObjectChanged(getID(), strObject, CSyncNotify::enDelete);
|
|
1288
|
+
// oo conflicts
|
|
1289
|
+
for( int i = 0; i < (int)vecAttrs.size(); i++ )
|
|
1290
|
+
{
|
|
1291
|
+
getDB().executeSQL("UPDATE changed_values SET sent=3 where object=? and attrib=? and source_id=? and update_type=?",
|
|
1292
|
+
strObject, vecAttrs.elementAt(i), getID(), "create" );
|
|
1293
|
+
}
|
|
1294
|
+
//
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
m_nDeleted++;
|
|
1298
|
+
}else if ( strCmd.compare("links") == 0 )
|
|
1299
|
+
{
|
|
1300
|
+
String strValue = attrIter.getCurString();
|
|
1301
|
+
processAssociations(strObject, strValue);
|
|
1302
|
+
|
|
1303
|
+
String strSqlUpdate = "UPDATE ";
|
|
1304
|
+
strSqlUpdate += getName() + " SET object=? WHERE object=?";
|
|
1305
|
+
getDB().executeSQL(strSqlUpdate.c_str(), strValue, strObject);
|
|
1306
|
+
|
|
1307
|
+
getDB().executeSQL("UPDATE changed_values SET object=?,sent=3 where object=? and source_id=? and update_type=?", strValue, strObject, getID(), "create" );
|
|
1308
|
+
getNotify().onObjectChanged(getID(), strObject, CSyncNotify::enCreate);
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
boolean CSyncSource::processBlob( const String& strCmd, const String& strObject, CAttrValue& oAttrValue )
|
|
1314
|
+
{
|
|
1315
|
+
//TODO: when server return delete with rhoblob postfix - delete isBlobAttr
|
|
1316
|
+
if ( !(oAttrValue.m_strBlobSuffix.length() > 0 || getDB().getAttrMgr().isBlobAttr(getID(), oAttrValue.m_strAttrib.c_str())) )
|
|
1317
|
+
return true;
|
|
1318
|
+
|
|
1319
|
+
boolean bDownload = true;
|
|
1320
|
+
String strDbValue = "";
|
|
1321
|
+
if ( !getDB().getAttrMgr().isOverwriteBlobFromServer(getID(), oAttrValue.m_strAttrib) )
|
|
1322
|
+
{
|
|
1323
|
+
if ( m_bSchemaSource )
|
|
1324
|
+
{
|
|
1325
|
+
String strSelect = String("SELECT ") + oAttrValue.m_strAttrib + " FROM " + getName() + " WHERE object=?";
|
|
1326
|
+
IDBResult res = getDB().executeSQL( strSelect.c_str(), strObject);
|
|
1327
|
+
if (!res.isEnd())
|
|
1328
|
+
{
|
|
1329
|
+
strDbValue = res.getStringByIdx(0);
|
|
1330
|
+
bDownload = strDbValue.length() == 0;
|
|
1331
|
+
}
|
|
1332
|
+
}else
|
|
1333
|
+
{
|
|
1334
|
+
IDBResult res = getDB().executeSQL(
|
|
1335
|
+
"SELECT value FROM object_values WHERE object=? and attrib=? and source_id=?",
|
|
1336
|
+
strObject, oAttrValue.m_strAttrib, getID() );
|
|
1337
|
+
if (!res.isEnd())
|
|
1338
|
+
{
|
|
1339
|
+
strDbValue = res.getStringByIdx(0);
|
|
1340
|
+
bDownload = strDbValue.length() == 0;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
if ( bDownload )
|
|
1346
|
+
{
|
|
1347
|
+
getDB().endTransaction();
|
|
1348
|
+
boolean bRes = downloadBlob(oAttrValue);
|
|
1349
|
+
getDB().startTransaction();
|
|
1350
|
+
|
|
1351
|
+
return bRes;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
oAttrValue.m_strValue = strDbValue;
|
|
1355
|
+
return true;
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
boolean CSyncSource::processServerBlobAttrs() {
|
|
1359
|
+
if ( m_bSchemaSource ) {
|
|
1360
|
+
return true;
|
|
1361
|
+
} else {
|
|
1362
|
+
static const String blobSfx = "-rhoblob";
|
|
1363
|
+
|
|
1364
|
+
getDB().startTransaction();
|
|
1365
|
+
IDBResult res = getDB().executeSQL( "SELECT source_attribs,blob_attribs from sources WHERE source_id=?", getID() );
|
|
1366
|
+
|
|
1367
|
+
Vector<String> attrsToRename;
|
|
1368
|
+
|
|
1369
|
+
String newAttrs = "";
|
|
1370
|
+
|
|
1371
|
+
for ( ; !res.isEnd(); res.next() )
|
|
1372
|
+
{
|
|
1373
|
+
String attrs = res.getStringByIdx(0);
|
|
1374
|
+
String blobs = res.getStringByIdx(1);
|
|
1375
|
+
|
|
1376
|
+
CTokenizer tokenizer(attrs,",");
|
|
1377
|
+
while (tokenizer.hasMoreTokens()) {
|
|
1378
|
+
String attrName = tokenizer.nextToken();
|
|
1379
|
+
if (!tokenizer.hasMoreTokens()) {
|
|
1380
|
+
break;
|
|
1381
|
+
}
|
|
1382
|
+
String attrVal = tokenizer.nextToken();
|
|
1383
|
+
|
|
1384
|
+
|
|
1385
|
+
if ( String_endsWith( attrName, blobSfx ) ) {
|
|
1386
|
+
if ( blobs.length() > 0 ) {
|
|
1387
|
+
blobs += ",";
|
|
1388
|
+
}
|
|
1389
|
+
blobs += attrName.substr(0,attrName.length()-blobSfx.length()) + "," + attrVal;
|
|
1390
|
+
attrsToRename.addElement(attrName);
|
|
1391
|
+
} else {
|
|
1392
|
+
if (newAttrs.length() > 0 ) {
|
|
1393
|
+
newAttrs += ",";
|
|
1394
|
+
}
|
|
1395
|
+
newAttrs += attrName + "," + attrVal;
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
LOG(TRACE) + "Updating attributes for source " + getName() + ". Old attribs=" + attrs + ", new attribs=" + newAttrs + ", blob attribs=" + blobs;
|
|
1400
|
+
|
|
1401
|
+
getDB().executeSQL("UPDATE sources SET source_attribs=?,blob_attribs=? WHERE source_id=?", newAttrs, blobs, getID() );
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
for ( int i = 0; i < (int)attrsToRename.size(); i++ )
|
|
1405
|
+
{
|
|
1406
|
+
String strAttr = (String)attrsToRename.elementAt(i);
|
|
1407
|
+
LOG(TRACE) + "Updating objects with blob attribute " + strAttr + " for source " + getName();
|
|
1408
|
+
getDB().executeSQL( "UPDATE object_values SET attrib=? WHERE attrib=? and source_id=?", strAttr.substr( 0, strAttr.length()-blobSfx.length()), strAttr, getID() );
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
getDB().endTransaction();
|
|
1412
|
+
}
|
|
1413
|
+
return true;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
|
|
1417
|
+
boolean CSyncSource::processAllBlobs()
|
|
1418
|
+
{
|
|
1419
|
+
if (m_bSchemaSource) {
|
|
1420
|
+
Vector<String> blobAttrs = getDB().getAttrMgr().getBlobAttrs( getID() );
|
|
1421
|
+
|
|
1422
|
+
for ( int i = 0; i < (int)blobAttrs.size(); i ++ )
|
|
1423
|
+
{
|
|
1424
|
+
String strAttr = (String)blobAttrs.elementAt(i);
|
|
1425
|
+
String sql = "SELECT object," + strAttr + " FROM " + getName();
|
|
1426
|
+
|
|
1427
|
+
IDBResult res = getDB().executeSQL( sql.c_str() );
|
|
1428
|
+
|
|
1429
|
+
LOG(TRACE) + "Processing blobs for source " + getName() + ", attribute " + strAttr;
|
|
1430
|
+
|
|
1431
|
+
for ( ; !res.isEnd(); res.next() )
|
|
1432
|
+
{
|
|
1433
|
+
String object = res.getStringByIdx(0);
|
|
1434
|
+
String value = res.getStringByIdx(1);
|
|
1435
|
+
|
|
1436
|
+
if ( value.find("://") != String::npos ) {
|
|
1437
|
+
LOG(TRACE) + "Processing remote blob: " + value;
|
|
1438
|
+
CAttrValue attr( strAttr, value );
|
|
1439
|
+
if ( !downloadBlob( attr ) ) {
|
|
1440
|
+
return false;
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
sql = "UPDATE " + getName() + " SET " + strAttr + "=? WHERE object=?";
|
|
1444
|
+
|
|
1445
|
+
getDB().executeSQL( sql.c_str(), attr.m_strValue, object );
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
} else {
|
|
1450
|
+
Vector<String> blobAttrs = getDB().getAttrMgr().getBlobAttrs( getID() );
|
|
1451
|
+
|
|
1452
|
+
for ( int i = 0; i < (int)blobAttrs.size(); i ++ )
|
|
1453
|
+
{
|
|
1454
|
+
String strAttr = (String)blobAttrs.elementAt(i);
|
|
1455
|
+
IDBResult res = getDB().executeSQL("SELECT object,value FROM object_values WHERE attrib=? and source_id=?", strAttr, getID());
|
|
1456
|
+
|
|
1457
|
+
LOG(TRACE) + "Processing blobs for source " + getName() + ", attribute " + strAttr;
|
|
1458
|
+
|
|
1459
|
+
for ( ; !res.isEnd(); res.next() )
|
|
1460
|
+
{
|
|
1461
|
+
String object = res.getStringByIdx(0);
|
|
1462
|
+
String value = res.getStringByIdx(1);
|
|
1463
|
+
|
|
1464
|
+
if ( value.find("://") != String::npos ) {
|
|
1465
|
+
LOG(TRACE) + "Processing remote blob: " + value;
|
|
1466
|
+
CAttrValue attr( strAttr, value );
|
|
1467
|
+
if ( !downloadBlob( attr ) ) {
|
|
1468
|
+
return false;
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
getDB().executeSQL("UPDATE object_values SET value=? where object=? and source_id=? and attrib=?", attr.m_strValue, object, getID(), strAttr);
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
return true;
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
boolean CSyncSource::checkFreezedProps(String strProp)
|
|
1481
|
+
{
|
|
1482
|
+
String strFreezedProps = getSync().getSourceOptions().getProperty(getID(), "freezed");
|
|
1483
|
+
|
|
1484
|
+
if ( strFreezedProps.length() > 0 )
|
|
1485
|
+
{
|
|
1486
|
+
CTokenizer oTokenizer( strFreezedProps, "," );
|
|
1487
|
+
boolean bFound =false;
|
|
1488
|
+
while (oTokenizer.hasMoreTokens() && (!bFound) )
|
|
1489
|
+
{
|
|
1490
|
+
String tok = oTokenizer.nextToken();
|
|
1491
|
+
if (tok.length() == 0)
|
|
1492
|
+
continue;
|
|
1493
|
+
|
|
1494
|
+
if (tok.compare(strProp)==0)
|
|
1495
|
+
{
|
|
1496
|
+
bFound = true;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
if (!bFound)
|
|
1501
|
+
{
|
|
1502
|
+
LOG(INFO) + "Skip Non-exist property : " + strProp + ". For model : " + getName();
|
|
1503
|
+
return false;
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
return true;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
void CSyncSource::makeFreezedPropsHash(rho::Hashtable<String, bool>& hash)
|
|
1511
|
+
{
|
|
1512
|
+
hash.clear();
|
|
1513
|
+
|
|
1514
|
+
String strFreezedProps = getSync().getSourceOptions().getProperty(getID(), "freezed");
|
|
1515
|
+
|
|
1516
|
+
if ( strFreezedProps.length() > 0 )
|
|
1517
|
+
{
|
|
1518
|
+
CTokenizer oTokenizer( strFreezedProps, "," );
|
|
1519
|
+
while (oTokenizer.hasMoreTokens() )
|
|
1520
|
+
{
|
|
1521
|
+
String tok = oTokenizer.nextToken();
|
|
1522
|
+
|
|
1523
|
+
if (tok.length() == 0)
|
|
1524
|
+
continue;
|
|
1525
|
+
|
|
1526
|
+
hash[tok] = true;
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
void CSyncSource::processServerCmd_Ver3(const String& strCmd, const String& strObject, const String& strAttriba, const String& strValuea, boolean bCheckUIRequest)//throws Exception
|
|
1532
|
+
{
|
|
1533
|
+
CAttrValue oAttrValue(strAttriba,strValuea);
|
|
1534
|
+
|
|
1535
|
+
if ( strCmd.compare("insert") == 0 )
|
|
1536
|
+
{
|
|
1537
|
+
if ( bCheckUIRequest && !checkFreezedProps(oAttrValue.m_strAttrib))
|
|
1538
|
+
return;
|
|
1539
|
+
|
|
1540
|
+
if ( !processBlob(strCmd,strObject,oAttrValue) )
|
|
1541
|
+
return;
|
|
1542
|
+
|
|
1543
|
+
IDBResult resInsert = getDB().executeSQLReportNonUnique("INSERT INTO object_values \
|
|
1544
|
+
(attrib, source_id, object, value) VALUES(?,?,?,?)",
|
|
1545
|
+
oAttrValue.m_strAttrib, getID(), strObject, oAttrValue.m_strValue );
|
|
1546
|
+
if ( resInsert.isNonUnique() )
|
|
1547
|
+
{
|
|
1548
|
+
getDB().executeSQL("UPDATE object_values \
|
|
1549
|
+
SET value=? WHERE object=? and attrib=? and source_id=?",
|
|
1550
|
+
oAttrValue.m_strValue, strObject, oAttrValue.m_strAttrib, getID() );
|
|
1551
|
+
|
|
1552
|
+
if ( getSyncType().compare("none") != 0 )
|
|
1553
|
+
{
|
|
1554
|
+
// oo conflicts
|
|
1555
|
+
getDB().executeSQL("UPDATE changed_values SET sent=4 where object=? and attrib=? and source_id=? and update_type=? and sent>1",
|
|
1556
|
+
strObject, oAttrValue.m_strAttrib, getID(), "create" );
|
|
1557
|
+
//
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
if ( getSyncType().compare("none") != 0 )
|
|
1562
|
+
getNotify().onObjectChanged(getID(),strObject, CSyncNotify::enUpdate);
|
|
1563
|
+
|
|
1564
|
+
m_nInserted++;
|
|
1565
|
+
}else if (strCmd.compare("delete") == 0)
|
|
1566
|
+
{
|
|
1567
|
+
getDB().executeSQL("DELETE FROM object_values where object=? and attrib=? and source_id=?", strObject, oAttrValue.m_strAttrib, getID() );
|
|
1568
|
+
|
|
1569
|
+
if ( getSyncType().compare("none") != 0 )
|
|
1570
|
+
{
|
|
1571
|
+
getNotify().onObjectChanged(getID(), strObject, CSyncNotify::enDelete);
|
|
1572
|
+
// oo conflicts
|
|
1573
|
+
getDB().executeSQL("UPDATE changed_values SET sent=3 where object=? and attrib=? and source_id=? and update_type=?", strObject, oAttrValue.m_strAttrib, getID(), "create" );
|
|
1574
|
+
//
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
m_nDeleted++;
|
|
1578
|
+
}else if ( strCmd.compare("links") == 0 )
|
|
1579
|
+
{
|
|
1580
|
+
processAssociations(strObject, oAttrValue.m_strValue);
|
|
1581
|
+
|
|
1582
|
+
getDB().executeSQL("UPDATE object_values SET object=? where object=? and source_id=?", oAttrValue.m_strValue, strObject, getID() );
|
|
1583
|
+
getDB().executeSQL("UPDATE changed_values SET object=?,sent=3 where object=? and source_id=? and update_type=?", oAttrValue.m_strValue, strObject, getID(), "create" );
|
|
1584
|
+
|
|
1585
|
+
getNotify().onObjectChanged(getID(), strObject, CSyncNotify::enCreate);
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
String CSyncSource::makeFileName(const CAttrValue& value)//throws Exception
|
|
1591
|
+
{
|
|
1592
|
+
String strExt = "";
|
|
1593
|
+
|
|
1594
|
+
URI uri(value.m_strValue);
|
|
1595
|
+
String strQuest = uri.getQueryString();
|
|
1596
|
+
|
|
1597
|
+
if (strQuest.length() > 0)
|
|
1598
|
+
{
|
|
1599
|
+
int nExt = strQuest.find("extension=");
|
|
1600
|
+
if ( nExt >= 0 )
|
|
1601
|
+
{
|
|
1602
|
+
int nExtEnd = strQuest.find("&", nExt);
|
|
1603
|
+
if (nExtEnd < 0 )
|
|
1604
|
+
nExtEnd = strQuest.length();
|
|
1605
|
+
|
|
1606
|
+
strExt = strQuest.substr(nExt+10, nExtEnd);
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
if ( strExt.length() == 0 )
|
|
1611
|
+
{
|
|
1612
|
+
String strFileName = uri.getLastNamePart();
|
|
1613
|
+
int nExt = strFileName.find_last_of('.');
|
|
1614
|
+
if ( nExt >= 0 )
|
|
1615
|
+
strExt = strFileName.substr(nExt);
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
if ( strExt.length() == 0 )
|
|
1619
|
+
strExt = ".bin";
|
|
1620
|
+
else if ( strExt.at(0) != '.' )
|
|
1621
|
+
strExt = "." + strExt;
|
|
1622
|
+
|
|
1623
|
+
static int g_nBlobCounter = 0;
|
|
1624
|
+
String fName = RHODESAPPBASE().getBlobsDirPath() + "/id_" + CLocalTime().toString(true,true) + convertToStringA(g_nBlobCounter) + strExt;
|
|
1625
|
+
g_nBlobCounter++;
|
|
1626
|
+
|
|
1627
|
+
return fName;
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
CAttrValue::CAttrValue(const String& strAttrib, const String& strValue)
|
|
1631
|
+
{
|
|
1632
|
+
m_strAttrib = strAttrib;
|
|
1633
|
+
m_strValue = strValue;
|
|
1634
|
+
|
|
1635
|
+
if ( String_endsWith(m_strAttrib,"-rhoblob") )
|
|
1636
|
+
{
|
|
1637
|
+
m_strBlobSuffix = "-rhoblob";
|
|
1638
|
+
m_strAttrib = m_strAttrib.substr(0,m_strAttrib.length()-m_strBlobSuffix.length());
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
boolean CSyncSource::downloadBlob(CAttrValue& value)//throws Exception
|
|
1643
|
+
{
|
|
1644
|
+
String fName = makeFileName( value );
|
|
1645
|
+
String url = value.m_strValue;
|
|
1646
|
+
|
|
1647
|
+
LOG(TRACE) + "Download blob: " + url + " => " + fName;
|
|
1648
|
+
|
|
1649
|
+
const char* nQuest = strchr(url.c_str(),'?');
|
|
1650
|
+
if ( nQuest > 0 )
|
|
1651
|
+
url += "&";
|
|
1652
|
+
else
|
|
1653
|
+
url += "?";
|
|
1654
|
+
url += "client_id=" + getSync().getClientID();
|
|
1655
|
+
|
|
1656
|
+
NetResponse resp = getNet().pullFile(url, fName, &getSync(), null, true, false);
|
|
1657
|
+
if ( !resp.isOK() )
|
|
1658
|
+
{
|
|
1659
|
+
CRhoFile::deleteFile(fName.c_str());
|
|
1660
|
+
//getSync().stopSync();
|
|
1661
|
+
m_nErrCode = RhoAppAdapter.getErrorFromResponse(resp);
|
|
1662
|
+
//m_strError = resp.getCharData();
|
|
1663
|
+
return false;
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
value.m_strValue = RHODESAPPBASE().getRelativeDBFilesPath( fName );
|
|
1667
|
+
|
|
1668
|
+
return true;
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
void CSyncSource::processToken(uint64 token)
|
|
1672
|
+
{
|
|
1673
|
+
if ( token > 1 && getToken() == token ){
|
|
1674
|
+
//Delete non-confirmed records
|
|
1675
|
+
|
|
1676
|
+
setToken( token ); //For m_bTokenFromDB = false;
|
|
1677
|
+
//getDB().executeSQL("DELETE FROM object_values where source_id=? and token=?", getID(), token );
|
|
1678
|
+
//TODO: add special table for id,token
|
|
1679
|
+
}else
|
|
1680
|
+
{
|
|
1681
|
+
setToken( token );
|
|
1682
|
+
getDB().executeSQL("UPDATE sources SET token=? where source_id=?", token, getID() );
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
bool CSyncSource::haveChangedValues()
|
|
1688
|
+
{
|
|
1689
|
+
IDBResult res = getDB().executeSQL("SELECT object FROM changed_values WHERE source_id=? and sent<=1 LIMIT 1 OFFSET 0", getID());
|
|
1690
|
+
return !res.isEnd();
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
}
|
|
1694
|
+
}
|