rhoconnect 3.4.5 → 4.0.0.beta.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (337) hide show
  1. data/CHANGELOG.md +57 -3
  2. data/Gemfile +9 -7
  3. data/Gemfile.lock +37 -37
  4. data/Rakefile +18 -7
  5. data/bench/benchapp/Gemfile +1 -1
  6. data/bench/benchapp/config.ru +0 -3
  7. data/bench/benchapp/controllers/ruby/application.rb +17 -0
  8. data/bench/benchapp/controllers/ruby/application_controller.rb +17 -0
  9. data/bench/benchapp/controllers/ruby/mock_adapter_controller.rb +8 -0
  10. data/bench/benchapp/controllers/ruby/queue_mock_adapter_controller.rb +8 -0
  11. data/bench/benchapp/{sources → models/ruby}/mock_adapter.rb +1 -1
  12. data/bench/benchapp/{sources → models/ruby}/queue_mock_adapter.rb +0 -0
  13. data/bench/benchapp/spec/{sources → models/ruby}/mock_adapter_spec.rb +1 -1
  14. data/bench/benchapp/spec/{sources → models/ruby}/queue_mock_adapter_spec.rb +1 -1
  15. data/bench/benchapp/spec/spec_helper.rb +2 -2
  16. data/bench/blobapp/Gemfile +1 -1
  17. data/bench/blobapp/config.ru +0 -3
  18. data/bench/blobapp/controllers/ruby/application_controller.rb +17 -0
  19. data/bench/blobapp/controllers/ruby/blob_adapter_controller.rb +8 -0
  20. data/bench/blobapp/{sources → models/ruby}/blob_adapter.rb +9 -2
  21. data/bench/blobapp/spec/{sources → models/ruby}/blob_adapter_spec.rb +1 -1
  22. data/bench/blobapp/spec/spec_helper.rb +1 -1
  23. data/bench/lib/bench/cli.rb +1 -1
  24. data/bench/scripts/blob_cud_script.rb +1 -1
  25. data/bench/scripts/query_md_script.rb +1 -1
  26. data/bench/scripts/query_only_script.rb +1 -1
  27. data/bench/scripts/query_script.rb +1 -1
  28. data/bench/scripts/test_query_script.rb +7 -1
  29. data/bench/spec/mock_adapter_spec.rb +1 -1
  30. data/bench/spec/result_spec.rb +3 -3
  31. data/bin/rhoconnect +5 -3
  32. data/commands/dtach/dtach_install.rb +2 -2
  33. data/commands/execute.rb +8 -3
  34. data/commands/generators/app.rb +3 -3
  35. data/commands/generators/controller.rb +6 -0
  36. data/commands/generators/model.rb +6 -0
  37. data/commands/generators/source.rb +3 -3
  38. data/commands/generators/update.rb +1 -1
  39. data/commands/redis/redis_about.rb +2 -2
  40. data/commands/redis/redis_download.rb +1 -1
  41. data/commands/redis/redis_install.rb +4 -3
  42. data/commands/redis/redis_restart.rb +4 -4
  43. data/commands/redis/redis_start.rb +5 -4
  44. data/commands/redis/redis_startbg.rb +5 -4
  45. data/commands/redis/redis_status.rb +13 -0
  46. data/commands/redis/redis_stop.rb +3 -3
  47. data/commands/rhoconnect/config.rb +28 -16
  48. data/commands/rhoconnect/flushdb.rb +1 -2
  49. data/commands/rhoconnect/get_token.rb +15 -11
  50. data/commands/rhoconnect/restart.rb +13 -5
  51. data/commands/rhoconnect/set_admin_password.rb +8 -8
  52. data/commands/rhoconnect/start.rb +74 -16
  53. data/commands/rhoconnect/startbg.rb +1 -1
  54. data/commands/rhoconnect/startdebug.rb +1 -1
  55. data/commands/rhoconnect/stop.rb +13 -1
  56. data/commands/rhoconnect/web.rb +5 -5
  57. data/commands/rhoconnect_console/console.rb +7 -5
  58. data/commands/{rhoconnect → rhoconnect_spec}/spec.rb +0 -0
  59. data/commands/rhoconnect_war/war.rb +9 -9
  60. data/commands/utilities/blank_app.ru +56 -0
  61. data/commands/utilities/redis_runner.rb +54 -19
  62. data/doc/authentication.txt +80 -6
  63. data/doc/blob-sync.txt +104 -97
  64. data/doc/bulk-sync.txt +1 -1
  65. data/doc/client-java.txt +3 -3
  66. data/doc/client-objc.txt +2 -2
  67. data/doc/client.txt +4 -4
  68. data/doc/command-line.txt +105 -200
  69. data/doc/data-partitioning.txt +40 -0
  70. data/doc/deploying.txt +249 -77
  71. data/doc/extending-rhoconnect-server.txt +40 -57
  72. data/doc/heroku-addon.txt +2 -0
  73. data/doc/install.txt +45 -95
  74. data/doc/introduction.txt +1 -1
  75. data/doc/java-plugin.txt +365 -190
  76. data/doc/metadata.txt +1 -1
  77. data/doc/migration.txt +108 -142
  78. data/doc/preparing-production.txt +1 -1
  79. data/doc/push-backend-setup.txt +2 -0
  80. data/doc/push-client-setup-android.txt +78 -0
  81. data/doc/push-client-setup-bb.txt +81 -0
  82. data/doc/push-client-setup-ios.txt +70 -0
  83. data/doc/push-client-setup-rps.txt +200 -0
  84. data/doc/push-client-setup.txt +63 -66
  85. data/doc/push-server-setup.txt +67 -40
  86. data/doc/push-testing.txt +29 -0
  87. data/doc/push.txt +21 -6
  88. data/doc/rest-api.txt +128 -55
  89. data/doc/rhoconnect-redis-stack.txt +120 -0
  90. data/doc/settings.txt +4 -12
  91. data/doc/source-adapters-intro.txt +28 -0
  92. data/doc/source-adapters.txt +235 -272
  93. data/doc/stats-middleware.txt +9 -29
  94. data/doc/supported-platforms.txt +21 -30
  95. data/doc/testing.txt +40 -42
  96. data/doc/tutorial.txt +72 -57
  97. data/examples/simple/Gemfile +1 -1
  98. data/examples/simple/application.rb +4 -5
  99. data/examples/simple/my_server.rb +2 -2
  100. data/examples/simple/settings/settings.yml +1 -1
  101. data/generators/rhoconnect.rb +151 -50
  102. data/generators/templates/application/Gemfile +1 -1
  103. data/generators/templates/application/Rakefile +3 -3
  104. data/generators/templates/application/config.ru +1 -4
  105. data/generators/templates/application/controllers/application_controller.rb +17 -0
  106. data/generators/templates/application/controllers/js/application_controller.js +14 -0
  107. data/generators/templates/application/controllers/ruby/application_controller.rb +17 -0
  108. data/generators/templates/application/package.json +8 -0
  109. data/generators/templates/application/rcgemfile +2 -5
  110. data/generators/templates/application/settings/settings.yml +3 -3
  111. data/generators/templates/application/spec/application_controller_spec.rb +23 -0
  112. data/generators/templates/application/spec/js_spec.rb +25 -0
  113. data/generators/templates/application/spec/spec_helper.rb +21 -7
  114. data/generators/templates/source/controllers/js/controller.js +7 -0
  115. data/generators/templates/source/controllers/ruby/controller.rb +8 -0
  116. data/generators/templates/source/controllers/ruby/controller_spec.rb +27 -0
  117. data/generators/templates/source/models/js/model.js +46 -0
  118. data/generators/templates/source/{source_adapter.rb → models/ruby/model.rb} +15 -10
  119. data/generators/templates/source/{source_spec.rb → models/ruby/model_spec.rb} +1 -1
  120. data/install.sh +5 -5
  121. data/installer/unix-like/create_texts.rb +2 -2
  122. data/installer/unix-like/rho_connect_install_constants.rb +2 -2
  123. data/installer/unix-like/rho_connect_install_utilities.rb +1 -1
  124. data/installer/utils/constants.rb +4 -4
  125. data/js-adapters/ballroom.js +216 -0
  126. data/js-adapters/node.rb +52 -0
  127. data/js-adapters/node_channel.rb +181 -0
  128. data/js-adapters/request.js +27 -0
  129. data/js-adapters/response.js +57 -0
  130. data/js-adapters/rhoconnect_helpers.js +60 -0
  131. data/js-adapters/router.js +60 -0
  132. data/js-adapters/server.js +5 -0
  133. data/lib/rhoconnect/api/app/ans_login.rb +3 -3
  134. data/lib/rhoconnect/api/app/bulk_data.rb +10 -10
  135. data/lib/rhoconnect/api/app/fast_delete.rb +11 -10
  136. data/lib/rhoconnect/api/app/fast_insert.rb +11 -10
  137. data/lib/rhoconnect/api/app/fast_update.rb +11 -10
  138. data/lib/rhoconnect/api/app/login.rb +5 -5
  139. data/lib/rhoconnect/api/app/push_deletes.rb +12 -11
  140. data/lib/rhoconnect/api/app/push_objects.rb +12 -11
  141. data/lib/rhoconnect/api/app/query.rb +8 -7
  142. data/lib/rhoconnect/api/app/queue_updates.rb +98 -94
  143. data/lib/rhoconnect/api/app/search.rb +8 -7
  144. data/lib/rhoconnect/api/client/client_get_db_doc.rb +5 -5
  145. data/lib/rhoconnect/api/client/client_set_db_doc.rb +8 -8
  146. data/lib/rhoconnect/api/client/create.rb +7 -7
  147. data/lib/rhoconnect/api/client/get_client_params.rb +4 -4
  148. data/lib/rhoconnect/api/client/list_client_docs.rb +17 -17
  149. data/lib/rhoconnect/api/client/register.rb +12 -12
  150. data/lib/rhoconnect/api/client/reset.rb +5 -5
  151. data/lib/rhoconnect/api/readstate/set_refresh_time.rb +9 -9
  152. data/lib/rhoconnect/api/source/get_source_params.rb +4 -4
  153. data/lib/rhoconnect/api/source/list_sources.rb +16 -16
  154. data/lib/rhoconnect/api/source/update_source_params.rb +6 -6
  155. data/lib/rhoconnect/api/store/get_db_doc.rb +4 -4
  156. data/lib/rhoconnect/api/store/set_db_doc.rb +7 -7
  157. data/lib/rhoconnect/api/system/get_adapter.rb +4 -4
  158. data/lib/rhoconnect/api/system/get_license_info.rb +8 -8
  159. data/lib/rhoconnect/api/system/login.rb +15 -15
  160. data/lib/rhoconnect/api/system/reset.rb +11 -11
  161. data/lib/rhoconnect/api/system/save_adapter.rb +4 -4
  162. data/lib/rhoconnect/api/system/stats.rb +22 -22
  163. data/lib/rhoconnect/api/user/create_user.rb +7 -7
  164. data/lib/rhoconnect/api/user/delete_client.rb +6 -6
  165. data/lib/rhoconnect/api/user/delete_user.rb +11 -10
  166. data/lib/rhoconnect/api/user/list_clients.rb +4 -4
  167. data/lib/rhoconnect/api/user/list_source_docs.rb +10 -10
  168. data/lib/rhoconnect/api/user/list_users.rb +3 -3
  169. data/lib/rhoconnect/api/user/ping.rb +3 -3
  170. data/lib/rhoconnect/api/user/show_user.rb +3 -3
  171. data/lib/rhoconnect/api/user/update_user.rb +5 -5
  172. data/lib/rhoconnect/api/user/user_get_db_doc.rb +5 -5
  173. data/lib/rhoconnect/api/user/user_set_db_doc.rb +10 -10
  174. data/lib/rhoconnect/api_token.rb +5 -6
  175. data/lib/rhoconnect/app.rb +6 -46
  176. data/lib/rhoconnect/application/init.rb +5 -2
  177. data/lib/rhoconnect/async.rb +76 -39
  178. data/lib/rhoconnect/bulk_data/bulk_data.rb +6 -4
  179. data/lib/rhoconnect/client.rb +59 -9
  180. data/lib/rhoconnect/condition/admin_required.rb +27 -0
  181. data/lib/rhoconnect/condition/client_required.rb +50 -0
  182. data/lib/rhoconnect/condition/login_required.rb +22 -0
  183. data/lib/rhoconnect/condition/source_required.rb +49 -0
  184. data/lib/rhoconnect/condition/verbs.rb +17 -0
  185. data/lib/rhoconnect/condition/verify_success.rb +19 -0
  186. data/lib/rhoconnect/controller/app_base.rb +74 -0
  187. data/lib/rhoconnect/controller/base.rb +68 -0
  188. data/lib/rhoconnect/controller/clients_controller.rb +79 -0
  189. data/lib/rhoconnect/controller/dynamic_adapter_controller.rb +93 -0
  190. data/lib/rhoconnect/controller/js_base.rb +124 -0
  191. data/lib/rhoconnect/controller/read_state_controller.rb +22 -0
  192. data/lib/rhoconnect/controller/source_adapter_base.rb +14 -0
  193. data/lib/rhoconnect/controller/sources_controller.rb +44 -0
  194. data/lib/rhoconnect/controller/store_controller.rb +25 -0
  195. data/lib/rhoconnect/controller/system_controller.rb +67 -0
  196. data/lib/rhoconnect/controller/users_controller.rb +99 -0
  197. data/lib/rhoconnect/db_adapter.rb +1 -3
  198. data/lib/rhoconnect/document.rb +159 -50
  199. data/lib/rhoconnect/handler/authenticate/execute_methods.rb +77 -0
  200. data/lib/rhoconnect/handler/authenticate/runner.rb +49 -0
  201. data/lib/rhoconnect/handler/authenticate.rb +3 -0
  202. data/lib/rhoconnect/handler/bulk_data.rb +28 -0
  203. data/lib/rhoconnect/handler/changes/engine.rb +271 -0
  204. data/lib/rhoconnect/handler/changes/execute_methods.rb +88 -0
  205. data/lib/rhoconnect/handler/changes/pass_through_runner.rb +11 -0
  206. data/lib/rhoconnect/handler/changes/runner.rb +53 -0
  207. data/lib/rhoconnect/handler/changes.rb +31 -0
  208. data/lib/rhoconnect/handler/helpers/auth_method.rb +29 -0
  209. data/lib/rhoconnect/handler/helpers/binding.rb +18 -0
  210. data/lib/rhoconnect/handler/helpers/bulk_data.rb +53 -0
  211. data/lib/rhoconnect/handler/helpers/source_job.rb +14 -0
  212. data/lib/rhoconnect/handler/helpers.rb +4 -0
  213. data/lib/rhoconnect/handler/plugin_callbacks/execute_methods.rb +99 -0
  214. data/lib/rhoconnect/handler/plugin_callbacks/runner.rb +28 -0
  215. data/lib/rhoconnect/handler/plugin_callbacks.rb +67 -0
  216. data/lib/rhoconnect/handler/query/engine.rb +93 -0
  217. data/lib/rhoconnect/handler/query/execute_methods.rb +21 -0
  218. data/lib/rhoconnect/handler/query/pass_through_runner.rb +35 -0
  219. data/lib/rhoconnect/handler/query/runner.rb +270 -0
  220. data/lib/rhoconnect/handler/query.rb +19 -0
  221. data/lib/rhoconnect/handler/search/engine.rb +60 -0
  222. data/lib/rhoconnect/handler/search/execute_methods.rb +32 -0
  223. data/lib/rhoconnect/handler/search/pass_through_runner.rb +18 -0
  224. data/lib/rhoconnect/handler/search/runner.rb +104 -0
  225. data/lib/rhoconnect/handler/search.rb +26 -0
  226. data/lib/rhoconnect/handler/sync.rb +29 -0
  227. data/lib/rhoconnect/jobs/source_job.rb +13 -4
  228. data/lib/rhoconnect/js_adapter.rb +79 -0
  229. data/lib/rhoconnect/license.rb +10 -2
  230. data/lib/rhoconnect/middleware/current_user.rb +14 -1
  231. data/lib/rhoconnect/middleware/helpers.rb +10 -93
  232. data/lib/rhoconnect/middleware/x_domain_session_wrapper.rb +1 -1
  233. data/lib/rhoconnect/model/base.rb +229 -0
  234. data/lib/rhoconnect/model/dynamic_adapter_model.rb +90 -0
  235. data/lib/rhoconnect/model/js_base.rb +121 -0
  236. data/lib/rhoconnect/ping/android.rb +1 -1
  237. data/lib/rhoconnect/predefined_adapters/bench_adapter.rb +7 -4
  238. data/lib/rhoconnect/read_state.rb +3 -3
  239. data/lib/rhoconnect/server.rb +159 -190
  240. data/lib/rhoconnect/source.rb +100 -11
  241. data/lib/rhoconnect/stats/record.rb +10 -10
  242. data/lib/rhoconnect/store.rb +905 -591
  243. data/lib/rhoconnect/{model.rb → store_orm.rb} +53 -115
  244. data/lib/rhoconnect/tasks.rb +18 -4
  245. data/lib/rhoconnect/test_methods.rb +30 -17
  246. data/lib/rhoconnect/user.rb +35 -17
  247. data/lib/rhoconnect/utilities.rb +1 -1
  248. data/lib/rhoconnect/version.rb +2 -2
  249. data/lib/rhoconnect/web-console/server.rb +29 -14
  250. data/lib/rhoconnect/web-console/views/home.js +10 -10
  251. data/lib/rhoconnect/web-console/views/new_ping.js +1 -1
  252. data/lib/rhoconnect.rb +120 -51
  253. data/rhoconnect.gemspec +4 -3
  254. data/spec/api/api_helper.rb +1 -6
  255. data/spec/api/app/fast_delete_spec.rb +4 -4
  256. data/spec/api/app/fast_insert_spec.rb +4 -4
  257. data/spec/api/app/fast_update_spec.rb +8 -8
  258. data/spec/api/app/push_deletes_spec.rb +2 -2
  259. data/spec/api/app/push_objects_spec.rb +5 -5
  260. data/spec/api/client/client_get_db_doc_spec.rb +6 -4
  261. data/spec/api/client/client_set_db_doc_spec.rb +3 -2
  262. data/spec/api/client/get_client_params_spec.rb +14 -0
  263. data/spec/api/client/list_client_docs_spec.rb +30 -20
  264. data/spec/api/client/reset_spec.rb +36 -0
  265. data/spec/api/source/get_source_params_spec.rb +23 -17
  266. data/spec/api/system/get_license_info_spec.rb +0 -20
  267. data/spec/api/system/login_spec.rb +8 -0
  268. data/spec/api/system/reset_spec.rb +0 -1
  269. data/spec/api/system/stats_spec.rb +5 -5
  270. data/spec/api/user/create_user_spec.rb +14 -6
  271. data/spec/api/user/delete_user_spec.rb +20 -18
  272. data/spec/api/user/list_users_spec.rb +5 -6
  273. data/spec/api/user/update_user_spec.rb +5 -4
  274. data/spec/apps/rhotestapp/config.ru +16 -1
  275. data/spec/apps/rhotestapp/controllers/js/js_sample_controller.js +23 -0
  276. data/spec/apps/rhotestapp/controllers/js/sample2_controller.js +32 -0
  277. data/spec/apps/rhotestapp/controllers/ruby/application_controller.rb +21 -0
  278. data/spec/apps/rhotestapp/controllers/ruby/sample_adapter_controller.rb +8 -0
  279. data/spec/apps/rhotestapp/models/js/js_sample.js +55 -0
  280. data/spec/apps/rhotestapp/models/js/sample2.js +25 -0
  281. data/spec/apps/rhotestapp/{sources → models/ruby}/base_adapter.rb +0 -0
  282. data/spec/apps/rhotestapp/{sources → models/ruby}/fixed_schema_adapter.rb +0 -0
  283. data/spec/apps/rhotestapp/{sources → models/ruby}/other_adapter.rb +0 -0
  284. data/spec/apps/rhotestapp/{sources → models/ruby}/sample_adapter.rb +0 -0
  285. data/spec/apps/rhotestapp/{sources → models/ruby}/simple_adapter.rb +2 -2
  286. data/spec/apps/rhotestapp/{sources → models/ruby}/sub_adapter.rb +0 -0
  287. data/spec/apps/rhotestapp/settings/settings.yml +0 -1
  288. data/spec/bulk_data/bulk_data_spec.rb +20 -5
  289. data/spec/cli/cli_spec.rb +83 -0
  290. data/spec/client_spec.rb +20 -17
  291. data/spec/client_sync_spec.rb +244 -406
  292. data/spec/controllers/js_base_spec.rb +89 -0
  293. data/spec/doc/doc_spec.rb +18 -18
  294. data/spec/document_spec.rb +29 -13
  295. data/spec/dynamic_adapter_spec.rb +6 -6
  296. data/spec/generator/generator_spec.rb +7 -4
  297. data/spec/jobs/bulk_data_job_spec.rb +14 -10
  298. data/spec/jobs/source_job_spec.rb +8 -8
  299. data/spec/license_spec.rb +5 -2
  300. data/spec/models/js_model_spec.rb +39 -0
  301. data/spec/node_spec.rb +42 -0
  302. data/spec/perf/store_perf_spec.rb +67 -12
  303. data/spec/ping/android_spec.rb +1 -1
  304. data/spec/read_state_spec.rb +1 -1
  305. data/spec/rhoconnect_spec.rb +1 -1
  306. data/spec/server/cors_spec.rb +14 -18
  307. data/spec/server/server_spec.rb +265 -88
  308. data/spec/server/stats_spec.rb +1 -1
  309. data/spec/source_adapter_spec.rb +54 -27
  310. data/spec/source_spec.rb +8 -3
  311. data/spec/source_sync_spec.rb +538 -468
  312. data/spec/spec_helper.rb +35 -4
  313. data/spec/stats/record_spec.rb +10 -10
  314. data/spec/{model_spec.rb → store_orm_spec.rb} +56 -54
  315. data/spec/store_spec.rb +159 -179
  316. data/spec/support/shared_examples.rb +36 -27
  317. data/spec/sync_states_spec.rb +40 -33
  318. data/spec/test_methods_spec.rb +18 -14
  319. data/spec/user_spec.rb +17 -30
  320. metadata +156 -52
  321. data/bench/benchapp/application.rb +0 -39
  322. data/bench/blobapp/application.rb +0 -44
  323. data/commands/rhoconnect/clean_start.rb +0 -9
  324. data/commands/rhoconnect/create_user.rb +0 -18
  325. data/commands/rhoconnect/delete_device.rb +0 -9
  326. data/commands/rhoconnect/delete_user.rb +0 -8
  327. data/commands/rhoconnect/reset.rb +0 -16
  328. data/commands/rhoconnect/reset_refresh.rb +0 -11
  329. data/generators/templates/application/application.rb +0 -43
  330. data/lib/rhoconnect/client_sync.rb +0 -434
  331. data/lib/rhoconnect/dynamic_adapter.rb +0 -91
  332. data/lib/rhoconnect/middleware/admin_user.rb +0 -23
  333. data/lib/rhoconnect/middleware/current_request.rb +0 -16
  334. data/lib/rhoconnect/middleware/login_required.rb +0 -22
  335. data/lib/rhoconnect/source_adapter.rb +0 -132
  336. data/lib/rhoconnect/source_sync.rb +0 -464
  337. data/spec/apps/rhotestapp/application.rb +0 -23
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rhoconnect/server'
3
+ require 'rhoconnect/web-console/server'
4
+ require 'resque/server'
5
+ if defined?(JRUBY_VERSION)
6
+ require 'puma'
7
+ else
8
+ require 'thin'
9
+ end
10
+
11
+ ROOT_PATH = File.expand_path('.')
12
+
13
+ # Rhoconnect server flags
14
+ # Rhoconnect::Server.enable :stats
15
+ Rhoconnect::Server.disable :run
16
+ Rhoconnect::Server.disable :clean_trace
17
+ Rhoconnect::Server.enable :raise_errors
18
+ Rhoconnect::Server.set :root, ROOT_PATH
19
+ Rhoconnect::Server.use Rack::Static, :urls => ['/data'], :root => Rhoconnect::Server.root
20
+ # Secret is stored in ~/.rhoconnect.yml
21
+ secret = YAML.load_file(File.join(ENV['HOME'], '.rhoconnect.yml'))[Rhoconnect.environment][:secret]
22
+ Rhoconnect::Server.set :secret, "#{secret}"
23
+
24
+ # Disable Async mode if Debugger is used
25
+ if ENV['DEBUG'] == 'yes'
26
+ Rhoconnect::Server.set :use_async_model, false
27
+ end
28
+
29
+ # Bootstrap the application
30
+ Rhoconnect.bootstrap(ROOT_PATH)
31
+
32
+ module Rhoconnect
33
+ def app
34
+ url_map = Rhoconnect.url_map
35
+ url_map['/resque'] = Resque::Server.new unless Rhoconnect.disable_resque_console
36
+ url_map['/console'] = RhoconnectConsole::Server.new unless Rhoconnect.disable_rc_console
37
+
38
+ return Rack::URLMap.new url_map
39
+ end
40
+ end
41
+
42
+ class ApplicationController < Rhoconnect::Controller::AppBase
43
+ register Rhoconnect::EndPoint
44
+
45
+ post "/login", :rc_handler => :authenticate,
46
+ :deprecated_route => {:verb => :post, :url => ['/application/clientlogin', '/api/application/clientlogin']} do
47
+ login, password = params[:login], params[:password]
48
+ true
49
+ end
50
+ get "/rps_login", :rc_handler => :rps_authenticate, :login_required => true do
51
+ login, password = params[:login], params[:password]
52
+ true
53
+ end
54
+ end
55
+
56
+ run Rhoconnect.app
@@ -1,3 +1,6 @@
1
+ require 'redis'
2
+ require 'socket'
3
+
1
4
  class RedisRunner
2
5
  def self.prefix
3
6
  "/usr/local/"
@@ -18,38 +21,58 @@ class RedisRunner
18
21
  '/tmp/redis.dtach'
19
22
  end
20
23
 
21
- def self.running?
22
- $redis_options ||= {}
23
- Redis.new($redis_options).ping == 'PONG'
24
+ def self.local_ip?(address)
25
+ (address == "localhost") || (address == "127.0.0.1")
26
+ end
27
+
28
+ def self.running?(inst = nil)
29
+ host, port = "localhost", 6379
30
+ host, port = inst.split(':')[0..1] if inst
31
+ Redis.new(:host => host, :port => port).ping =~ /PONG/
24
32
  rescue
25
33
  false
26
34
  end
27
35
 
28
- def self.start
36
+ def self.start(redis_array)
29
37
  if windows?
38
+ # TODO: There's no support for redis array on Windows.
39
+ # An alpha version of Redis 2.6 was released 01/22/2013 (https://github.com/MSOpenTech/redis)
40
+ puts "*** Warning: Redis array is not implemented on Windows" if redis_array.size > 1
30
41
  puts "Starting redis in a new window..."
31
42
  system "start #{File.join(redis_home,'redis-server')} #{File.join(redis_home,'redis.conf')}" rescue
32
43
  "redis-server not installed on your path, please install redis."
33
- elsif defined?(JRUBY_VERSION)
34
- puts "Starting redis ..."
35
- system "redis-server #{redisconfdir}"
36
- else
37
- puts 'Detach with Ctrl+\ Re-attach with rhoconnect redis-attach'
38
- sleep 1
39
- command = "dtach -A #{dtach_socket} redis-server #{redisconfdir}"
44
+ elsif (redis_array.size == 1)
45
+ host, port = redis_array[0].split(':')[0..1]
46
+ puts "Starting redis server ..."
47
+ if defined?(JRUBY_VERSION)
48
+ command = "redis-server --port #{port} &"
49
+ else
50
+ puts 'Detach with Ctrl+\ Re-attach with rhoconnect redis-attach'
51
+ sleep 1
52
+ command = "dtach -A #{dtach_socket} redis-server --port #{port}"
53
+ end
40
54
  system command
55
+ else
56
+ puts "Starting redis servers ..."
57
+ redis_array.each do |cfg|
58
+ host, port = cfg.split(':')[0..1]
59
+ system("redis-server --port #{port} &") if RedisRunner.local_ip?(host)
60
+ end
41
61
  end
42
62
  end
43
63
 
44
64
  # this function is used with Rhostudio where there is no terminal
45
- def self.startbg
65
+ def self.startbg(redis_array)
46
66
  if windows?
47
67
  puts "Starting redis in a new window..."
48
68
  system "start #{File.join(redis_home,'redis-server')} #{File.join(redis_home,'redis.conf')}" rescue
49
69
  "redis-server not installed on your path, please install redis."
50
70
  else
51
71
  puts "Starting redis ..."
52
- system "redis-server #{redisconfdir} &"
72
+ redis_array.each do |cfg|
73
+ host, port = cfg.split(':')[0..1]
74
+ system("redis-server --port #{port} &") if RedisRunner.local_ip?(host)
75
+ end
53
76
  end
54
77
  end
55
78
 
@@ -57,14 +80,26 @@ class RedisRunner
57
80
  system "dtach -a #{dtach_socket}"
58
81
  end
59
82
 
60
- def self.stop
61
- $redis_options ||= {}
62
- Redis.new($redis_options).shutdown rescue nil
83
+ def self.stop(redis_array)
84
+ if windows?
85
+ Redis.new.shutdown rescue nil
86
+ else
87
+ redis_array.each do |cfg|
88
+ host, port = cfg.split(':')[0..1]
89
+ Redis.new(:port => port).shutdown rescue nil if RedisRunner.local_ip?(host)
90
+ end
91
+ end
63
92
  end
64
93
 
65
- def self.flushdb
66
- $redis_options ||= {}
67
- Redis.new($redis_options).flushdb rescue nil
94
+ def self.flushdb (redis_array)
95
+ if windows?
96
+ Redis.new.flushdb rescue nil
97
+ else
98
+ redis_array.each do |cfg|
99
+ host, port = cfg.split(':')[0..1]
100
+ Redis.new(:port => "#{port}").flushdb rescue nil if RedisRunner.local_ip?(host)
101
+ end
102
+ end
68
103
  end
69
104
 
70
105
  end
@@ -1,7 +1,7 @@
1
1
  Device Authentication in RhoConnect
2
2
  ===
3
3
 
4
- The generated RhoConnect application code includes a file at the root called "application.rb" which contains an "authenticate" hook. This method is called when a device first connects to the RhoConnect application and provides username/password credentials.
4
+ The generated RhoConnect application code includes a file called "application_controller.rb" which contains an implementation for the "login" route. This route is called when a device first connects to the RhoConnect application and provides username/password credentials.
5
5
 
6
6
  ## Authentication Workflow
7
7
 
@@ -10,10 +10,12 @@ The following diagram shows how this authenticate method is called:
10
10
  <img src="https://img.skitch.com/20110111-g2ujk785gak2kfgfrspq1w8u8j.png"/>
11
11
 
12
12
  ## Example
13
- If your backend service requires authentication, simply add code to the authenticate method and return true if authentication was successful or false to deny access to the application from this device. For example:
13
+ If your backend service requires authentication, simply add code to the login route and return true if authentication was successful or false to deny access to the application from this device. For example:
14
14
 
15
15
  :::ruby
16
- def authenticate(username, password, session)
16
+ post "/login", :rc_handler => :authenticate do
17
+ username = params[:login]
18
+ password = params[:password]
17
19
  success = false
18
20
  # ... connect to backend using API and authenticate ...
19
21
  result = do_custom_authentication(username,password)
@@ -29,8 +31,10 @@ If your backend service requires authentication, simply add code to the authenti
29
31
  If your actual user name is different than the username that is input into the client, you can change the username by returning a string instead of true if authentication was successful.
30
32
 
31
33
  :::ruby
32
- def authenticate(username, password, session)
33
- success = false
34
+ post "/login", :rc_handler => :authenticate do
35
+ username = params[:login]
36
+ password = params[:password]
37
+ success = false
34
38
  # ... connect to backend using API and authenticate ...
35
39
  result = do_custom_authentication(username,password)
36
40
  if result.code == 200
@@ -49,7 +53,9 @@ The code sample above demonstrates authentication by calling a method you would
49
53
  :::ruby
50
54
  require 'net/ldap'
51
55
 
52
- def authenticate(username, password, session)
56
+ post "/login", :rc_handler => :authenticate do
57
+ username = params[:login]
58
+ password = params[:password]
53
59
  success = false
54
60
  ldap = Net::LDAP.new
55
61
  ldap.host = "localhost"
@@ -74,3 +80,71 @@ This example uses the [net-ldap](https://github.com/RoryO/ruby-net-ldap) gem. T
74
80
 
75
81
  For more details about LDAP, please visit [http://www.openldap.org/](http://www.openldap.org/).
76
82
 
83
+ ## X509 Example
84
+ The code sample below demonstrates using an X509 certificate for authentication. See <a href='http://wiki.pentaho.com/display/ServerDoc2x/Authentication+via+X.509+Client+Certificate' target='_blank'>X509 certificate generation</a> for more information about generating a cert. You can also view a <a href='https://github.com/rhomobile/x509-auth-sample' target='_blank'>sample project</a> of the code below.
85
+
86
+
87
+ Inside of your rhoconnect app you can replace the password parameter with a pem file parameter. This parameter is expecting a string formatted for pem with your certificate followed by your private key.
88
+ :::ruby
89
+
90
+ require 'socket'
91
+ require 'openssl'
92
+
93
+ post "/login", :rc_handler => :authenticate do
94
+ username = params[:login]
95
+ pem = params[:password]
96
+ #assuming pem file has certificate and then private key below in pem format
97
+ pem_arr = pem.split("-----END CERTIFICATE-----")
98
+ pem_arr[0] << "-----END CERTIFICATE-----"
99
+
100
+ socket = TCPSocket.new('my.secureserver.com', 4567)
101
+
102
+ ssl_context = OpenSSL::SSL::SSLContext.new
103
+
104
+ ssl_context.cert = OpenSSL::X509::Certificate.new(pem_arr[0].strip)
105
+ ssl_context.key = OpenSSL::PKey::RSA.new(pem_arr[1].strip)
106
+
107
+ ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
108
+ ssl_socket.sync_close = true
109
+
110
+ ca_cert = OpenSSL::X509::Certificate.new(File.open("CA.crt"))
111
+
112
+ if ssl_socket.connect
113
+ puts "socket connected correctly"
114
+ return true
115
+ else
116
+ puts "socket failed to connnect"
117
+ return false
118
+ end
119
+
120
+ end
121
+
122
+ A simple sinatra app listening on port 4567 for connections might look something like this.
123
+
124
+ :::ruby
125
+ require 'rubygems'
126
+ require 'socket'
127
+ require 'openssl'
128
+
129
+ socket = TCPServer.new('my.secureserver.com', 4567)
130
+
131
+ ssl_context = OpenSSL::SSL::SSLContext.new()
132
+ ssl_context.cert = OpenSSL::X509::Certificate.new(File.open("server.crt"))
133
+ ssl_context.key = OpenSSL::PKey::RSA.new(File.open("server.key"))
134
+
135
+ ca_cert = OpenSSL::X509::Certificate.new(File.open("CA.crt"))
136
+
137
+ ssl_socket = OpenSSL::SSL::SSLServer.new(socket, ssl_context)
138
+
139
+
140
+ loop do
141
+ connection = ssl_socket.accept
142
+ Thread.new {
143
+ begin
144
+ #do something
145
+ rescue
146
+ $stderr.puts $!
147
+ end
148
+ }
149
+ end
150
+
data/doc/blob-sync.txt CHANGED
@@ -5,78 +5,79 @@ Synchronizing images or binary objects between RhoConnect and the client is decl
5
5
  **NOTE: The example below shows how to synchronize an image created by the device's camera, but could be applied to any arbitrary files on the device.**
6
6
 
7
7
  ## Synchronizing from Device to RhoConnect
8
- Suppose you have a [Rhom model](/rhodes/rhom) called "Image" and you have a [camera callback function](/rhodes/device-caps#camera) defined in the Image model's controller:
9
-
10
- :::ruby
11
- def camera_callback
12
- if @params['status'] == 'ok'
13
- #create image record in the DB
14
- image = Image.new({'image_uri'=>@params['image_uri']})
15
- image.save
16
- SyncEngine.dosync
17
- end
18
- #reply on the callback
19
- render :action => :ok, :layout => false
20
- end
21
-
8
+ Suppose you have a [Rhom model](/rhodes/rhom) called "Image" and you have a [camera callback function](/rhodes/device-caps#camera) defined in the Rhodes Image model's controller:
9
+
10
+ :::ruby
11
+ def camera_callback
12
+ if @params['status'] == 'ok'
13
+ #create image record in the DB
14
+ image = Image.new({'image_uri'=>@params['image_uri']})
15
+ image.save
16
+ SyncEngine.dosync
17
+ end
18
+ #reply on the callback
19
+ render :action => :ok, :layout => false
20
+ end
21
+
22
22
  When this is executed in a Rhodes application:
23
23
 
24
24
  * This callback triggers a sync after saving saving an image.
25
25
 
26
26
  * Then Rhodes will push the image file to the RhoConnect application by HTTP POST.
27
27
 
28
- * `application.rb#store_blob` is called for optional pre-processing of the file. This is useful in cases where you want to preserve the filename that Rhodes sent.
28
+ * `image.rb#store_blob` is called for pre-processing of the file.
29
+ NOTE: You must implement this method inside of your Source Adapter Model and do not use the tempfile provided by Rack, because RhoConnect processing is asynchronous and there is no guarantee that the temporary file will exist at the actual time when `create` is called.
29
30
 
30
- The following example stores the `:filename` argument as another object attribute.
31
+ The following example stores the file permanently and keeps its `:filename` argument as another object attribute.
31
32
 
32
- :::ruby
33
- def store_blob(obj,field_name,blob)
34
- obj['filename'] = blob[:filename]
35
- super
33
+ :::ruby
34
+ def store_blob(obj,field_name,blob)
35
+ # ... custom code to store the blob file ...
36
+ my_stored_filename = do_custom_store[blob[:filename]]
37
+ obj['filename'] = my_stored_filename
36
38
  end
37
39
 
38
- * The RhoConnect source adapter tied to this Rhom model processes the blob in the `create` method.
40
+ * The RhoConnect source adapter model tied to this Rhom model processes the blob in the `create` method.
39
41
 
40
42
  The following example takes the blob and stores it in S3:
41
43
 
42
- :::ruby
43
- def create(create_hash)
44
- # this would be a blob attribute, points to a tempfile
45
- # containing the raw post data
46
- name = create_hash["image_uri"]
47
-
48
- # filename we saved in application.rb#store_blob method
49
- basename = create_hash["filename"]
50
- S3Object.store(
51
- basename,
52
- open(name),
53
- @bucket,
54
- :access => :public_read
55
- )
56
- basename #=> object id here is the filename
57
- end
44
+ :::ruby
45
+ def create(create_hash)
46
+ # this would be a blob attribute, points to a tempfile
47
+ # containing the raw post data
48
+ name = create_hash["image_uri"]
49
+ # filename we saved in application.rb#store_blob method
50
+ basename = create_hash["filename"]
51
+ S3Object.store(
52
+ basename,
53
+ open(name),
54
+ @bucket,
55
+ :access => :public_read
56
+ )
57
+ basename #=> object id here is the filename
58
+ end
58
59
 
59
60
  In this example, we store the image blob to s3 so we can query it later. See the "image" source adapter that comes with [the rhodes-samples-server](https://github.com/rhomobile/rhodes-samples-server/blob/master/sources/image.rb).
60
61
 
61
- ## Query for Blobs in the Source Adapter
62
+ ## Query for Blobs in the Source Adapter Model
62
63
 
63
64
  In your query call, you should store the URL to images in the blob attribute so that the device can fetch the image when it synchronizes.
64
65
 
65
- :::ruby
66
- def query(params=nil)
67
- @result={}
68
- Bucket.find(@bucket).objects.each do |entry|
69
- new_item = {
70
- 'image_uri-rhoblob' => @baseurl+@bucket+'/'+File.basename(entry.key)
71
- }
72
- @result[entry.key] = new_item
73
- end
74
- @result
75
- end
66
+ :::ruby
67
+ def query(params=nil)
68
+ @result={}
69
+ Bucket.find(@bucket).objects.each do |entry|
70
+ new_item = {
71
+ 'image_uri-rhoblob' => @baseurl+@bucket+'/'+File.basename(entry.key)
72
+ }
73
+ @result[entry.key] = new_item
74
+ end
75
+ @result
76
+ end
76
77
 
77
78
  Here we save the image URL to an attribute `image_uri-rhoblob`. This will correspond to the `image_uri` attribute in our Rhom model above.
78
79
 
79
- **NOTE: In order for Rhodes to automatically recognize a blob attribute, the attribute name must end with "-rhoblob". In the above example, `image_uri` was our Rhom attribute, so our source adapter assigned `image_uri-rhoblob` with the blob URL.**
80
+ **NOTE: In order for Rhodes to automatically recognize a blob attribute, the attribute name must end with "-rhoblob". In the above example, `image_uri` was our Rhom attribute, so our source adapter model assigned `image_uri-rhoblob` with the blob URL.**
80
81
 
81
82
  ### Blob file name and extension on client
82
83
  File name is generated on client when downloading. File extension is determine by:
@@ -85,53 +86,59 @@ File name is generated on client when downloading. File extension is determine b
85
86
  * If no extension parameter the blob URL then extension is extracted from blob URL itself(looking for '.' from the end of the URL)
86
87
  * If still no file extension found, then '.bin' is used
87
88
 
88
- A complete image source adapter that stores files in S3 might look like:
89
-
90
- :::ruby
91
- require 'aws/s3'
92
- class Image < SourceAdapter
93
- include AWS::S3
94
-
95
-
96
- def initialize(source,credential)
97
- AWS::S3::Base.establish_connection!(
98
- :access_key_id => ENV['AMAZON_ACCESS_KEY_ID'],
99
- :secret_access_key => ENV['AMAZON_SECRET_ACCESS_KEY']
100
- )
101
- @baseurl = 'http://s3.amazonaws.com/'
102
- @bucket = 'rhodes-samples-images'
103
- super(source,credential)
104
- end
105
-
106
- def query(params=nil)
107
- @result={}
108
- Bucket.find(@bucket).objects.each do |entry|
109
- new_item = {
110
- 'image_uri-rhoblob' => @baseurl+@bucket+'/'+File.basename(entry.key)
111
- }
112
- @result[entry.key] = new_item
113
- end
114
- @result
115
- end
116
-
117
- def create(create_hash)
118
- puts "Creating: #{create_hash.inspect}"
119
- name = create_hash["image_uri"]
120
- basename = create_hash["filename"]
121
- S3Object.store(
122
- basename,
123
- open(name),
124
- @bucket,
125
- :access => :public_read
126
- )
127
- basename
128
- end
129
-
130
- def delete(delete_hash)
131
- puts "Removing: #{delete_hash.inspect}"
132
- S3Object.delete delete_hash['id'], @bucket
133
- end
134
- end
89
+ A complete image source adapter model that stores files in S3 might look like:
90
+
91
+ :::ruby
92
+ require 'aws/s3'
93
+ class Image < Rhoconnect::Model::Base
94
+ include AWS::S3
95
+
96
+
97
+ def initialize(source,credential)
98
+ AWS::S3::Base.establish_connection!(
99
+ :access_key_id => ENV['AMAZON_ACCESS_KEY_ID'],
100
+ :secret_access_key => ENV['AMAZON_SECRET_ACCESS_KEY']
101
+ )
102
+ @baseurl = 'http://s3.amazonaws.com/'
103
+ @bucket = 'rhodes-samples-images'
104
+ super(source,credential)
105
+ end
106
+
107
+ def query(params=nil)
108
+ @result={}
109
+ Bucket.find(@bucket).objects.each do |entry|
110
+ new_item = {
111
+ 'image_uri-rhoblob' => @baseurl+@bucket+'/'+File.basename(entry.key)
112
+ }
113
+ @result[entry.key] = new_item
114
+ end
115
+ @result
116
+ end
117
+
118
+ def create(create_hash)
119
+ puts "Creating: #{create_hash.inspect}"
120
+ name = create_hash["image_uri"]
121
+ basename = create_hash["filename"]
122
+ S3Object.store(
123
+ basename,
124
+ open(name),
125
+ @bucket,
126
+ :access => :public_read
127
+ )
128
+ basename
129
+ end
130
+
131
+ def delete(delete_hash)
132
+ puts "Removing: #{delete_hash.inspect}"
133
+ S3Object.delete delete_hash['id'], @bucket
134
+ end
135
+
136
+ def store_blob(obj,field_name,blob)
137
+ # ... custom code to store the blob file ...
138
+ my_stored_filename = do_custom_store[blob[:filename]]
139
+ obj['filename'] = my_stored_filename
140
+ end
141
+ end
135
142
 
136
143
  ## Rhodes Sample Code
137
144
  See controller and view in the [app/Blob directory](https://github.com/rhomobile/rhodes-system-api-samples/tree/master/app/Blob) of the [System API Samples application](http://github.com/rhomobile/rhodes-system-api-samples/tree/master) for a complete Rhodes code sample.
data/doc/bulk-sync.txt CHANGED
@@ -8,7 +8,7 @@ If and when the Rhodes application issues a request to get bulk data, the RhoCon
8
8
 
9
9
  * Queue a [resque background job](http://github.com/defunkt/resque) which will run the bulk sync process.
10
10
 
11
- * Execute the ['login,'query','logoff' methods](/rhoconnect/source-adapters#source-adapter-api) of all source adapters matching the [requested data partition](/rhoconnect/source-adapters#data-partitioning) to get latest set of objects from the backend service
11
+ * Execute the ['login,'query','logoff' methods](/rhoconnect/source-adapters#source-adapter-api) of all source adapter models matching the [requested data partition](/rhoconnect/source-adapters#data-partitioning) to get latest set of objects from the backend service
12
12
 
13
13
  * Generate appropriate database files for the device - hsqldb for Blackberry and sqlite for the rest of them. RhoConnect will generate sqlite files for iOS, Android, and Windows Mobile clients and hsqldb files for Blackberry (if enabled).
14
14
 
data/doc/client-java.txt CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Getting started
4
4
 
5
- * The RhoConnect Client is part of the Rhodes repository. You can get it [on github](https://github.com/rhomobile/rhodes/downloads) (select the latest 'rhoconnect-client' package).
5
+ * The RhoConnect Client is part of the Rhoconnect-client repository. You can get it [on github](https://github.com/rhomobile/rhodes/downloads) (select the latest 'rhoconnect-client' package).
6
6
 
7
7
  * The RhoConnect Client for Android contains two files:
8
8
 
@@ -10,14 +10,14 @@
10
10
 
11
11
  ** librhoconnectclient.so - native part of RhoConnect Client library
12
12
 
13
- These can be build from <rhodes>/rhoconnect-client directory with next command
13
+ These can be build from <rhoconnect-client>/rhoconnect-client directory with next command
14
14
 
15
15
  :::shell
16
16
  $>rake android:default
17
17
 
18
18
  * Create new Android project or open existing one in Eclipse. Add rhoimple.jar to your project build path and copy librhoconnectclient.so to <project_root>/libs/armeabi, so both Java and native parts of RhoConnect Client library will link with your project.
19
19
 
20
- * Copy all files and subfolders from <rhodes>/rhoconnect-client/Java/RhoConnect/assets to assets folder of your Android project.
20
+ * Copy all files and subfolders from <rhoconnect-client>/rhoconnect-client/Java/RhoConnect/assets to assets folder of your Android project.
21
21
 
22
22
  ## RhoConnectClient initialization
23
23
 
data/doc/client-objc.txt CHANGED
@@ -7,7 +7,7 @@ Source Code
7
7
  -----------
8
8
  The source code for the RhoConnect client store example is located here.
9
9
 
10
- * [rhoconnect-client\Samples\ObjectiveC\store](http://github.com/rhomobile/rhodes/tree/master/rhoconnect-client/Samples/ObjectiveC/store/)
10
+ * [rhoconnect-client\Samples\ObjectiveC\store](http://github.com/rhomobile/rhoconnect-client/tree/master/rhoconnect-client/Samples/ObjectiveC/store/)
11
11
 
12
12
  Pre-requisite Reading
13
13
  ---------------------
@@ -31,7 +31,7 @@ Pre-requisite Reading
31
31
 
32
32
  ## Setup
33
33
 
34
- The RhoConnect Client is part of the Rhodes repository; it contains files that you will need to add to your Xcode project. You can get the client [on github](https://github.com/rhomobile/rhodes/downloads). (Select the latest 'rhoconnect-client' package).
34
+ The RhoConnect Client is part of the Rhoconnect-client repository; it contains files that you will need to add to your Xcode project. You can get the client [on github](https://github.com/rhomobile/rhodes/downloads). (Select the latest 'rhoconnect-client' package).
35
35
 
36
36
  Create a new Xcode project or open an existing one in Xcode.
37
37
 
data/doc/client.txt CHANGED
@@ -6,7 +6,7 @@ Rhoconnect Client is a library to add sync data capability to your applications.
6
6
  ## Objective-C Client
7
7
 
8
8
  ### Getting started
9
- * The RhoConnect Client is part of the Rhodes repository. You can get it [on github](https://github.com/rhomobile/rhodes/downloads) (select the latest 'rhoconnect-client' package).
9
+ * The RhoConnect Client is part of the Rhoconnect-client repository. You can get it [on github](https://github.com/rhomobile/rhodes/downloads) (select the latest 'rhoconnect-client' package).
10
10
 
11
11
  * Create new project or open existing one in XCode. Add `<rhoconnect-client>/objectivec/RhoConnectClient.xcodeproj` as dependency to your project, so the RhoConnectClient library will link with your project.
12
12
 
@@ -410,7 +410,7 @@ These can be build from <rhodes>/rhoconnect-client directory with next command
410
410
 
411
411
  * Create new Android project or open existing one in Eclipse. Add rhoimple.jar to your project build path and copy librhoconnectclient.so to <project_root>/libs/armeabi, so both Java and native parts of RhoConnect Client library will link with your project.
412
412
 
413
- * Copy all files and subfolders from <rhodes>/rhoconnect-client/Java/RhoConnect/assets to assets folder of your Android project.
413
+ * Copy all files and subfolders from <rhoconnect-client>/rhoconnect-client/Java/RhoConnect/assets to assets folder of your Android project.
414
414
 
415
415
  ### RhoConnectClient initialization
416
416
 
@@ -610,8 +610,8 @@ Also several utility classes from com.rhomobile.rhodes package can be used. Thes
610
610
 
611
611
  ### Samples
612
612
 
613
- * See android_store sample [rhoconnect-client\Samples\Java\android_store](http://github.com/rhomobile/rhodes/tree/master/rhoconnect-client/Samples/Java/android_store/) as an example.
614
- * See android test Eclipse project [rhoconnect-client\Java\Android\test](http://github.com/rhomobile/rhodes/tree/master/rhoconnect-client/Java/Android/test/) as another example.
613
+ * See android_store sample [rhoconnect-client\Samples\Java\android_store](http://github.com/rhomobile/rhoconnect-client/tree/master/rhoconnect-client/Samples/Java/android_store/) as an example.
614
+ * See android test Eclipse project [rhoconnect-client\Java\Android\test](http://github.com/rhomobile/rhoconnect-client/tree/master/rhoconnect-client/Java/Android/test/) as another example.
615
615
 
616
616
  ## Packaging RhoConnect Client
617
617
  To package the RhoConnect Client archive for distribution, go to the top of the rhodes repository and run: