PageRenderTime 160ms CodeModel.GetById 37ms RepoModel.GetById 0ms app.codeStats 0ms

/src/net/sqlcipher/BulkCursorToCursorAdaptor.java

https://bitbucket.org/leispire/android-database-sqlcipher
Java | 319 lines | 208 code | 45 blank | 66 comment | 27 complexity | 788b417b2a78048edf4530650b448c94 MD5 | raw file
  1. /*
  2. * Copyright (C) 2006 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package net.sqlcipher;
  17. import java.util.Map;
  18. import android.database.CharArrayBuffer;
  19. import android.database.ContentObserver;
  20. import android.database.DataSetObserver;
  21. import android.os.Bundle;
  22. import android.os.RemoteException;
  23. import android.util.Log;
  24. /**
  25. * Adapts an {@link IBulkCursor} to a {@link Cursor} for use in the local
  26. * process.
  27. *
  28. * {@hide}
  29. */
  30. public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor {
  31. private static final String TAG = "BulkCursor";
  32. private SelfContentObserver mObserverBridge;
  33. private IBulkCursor mBulkCursor;
  34. private int mCount;
  35. private String[] mColumns;
  36. private boolean mWantsAllOnMoveCalls;
  37. public void set(IBulkCursor bulkCursor) {
  38. mBulkCursor = bulkCursor;
  39. try {
  40. mCount = mBulkCursor.count();
  41. mWantsAllOnMoveCalls = mBulkCursor.getWantsAllOnMoveCalls();
  42. // Search for the rowID column index and set it for our parent
  43. mColumns = mBulkCursor.getColumnNames();
  44. mRowIdColumnIndex = findRowIdColumnIndex(mColumns);
  45. } catch (RemoteException ex) {
  46. Log.e(TAG, "Setup failed because the remote process is dead");
  47. }
  48. }
  49. /**
  50. * Version of set() that does fewer Binder calls if the caller
  51. * already knows BulkCursorToCursorAdaptor's properties.
  52. */
  53. public void set(IBulkCursor bulkCursor, int count, int idIndex) {
  54. mBulkCursor = bulkCursor;
  55. mColumns = null; // lazily retrieved
  56. mCount = count;
  57. mRowIdColumnIndex = idIndex;
  58. }
  59. /**
  60. * Returns column index of "_id" column, or -1 if not found.
  61. */
  62. public static int findRowIdColumnIndex(String[] columnNames) {
  63. int length = columnNames.length;
  64. for (int i = 0; i < length; i++) {
  65. if (columnNames[i].equals("_id")) {
  66. return i;
  67. }
  68. }
  69. return -1;
  70. }
  71. /**
  72. * Gets a SelfDataChangeOberserver that can be sent to a remote
  73. * process to receive change notifications over IPC.
  74. *
  75. * @return A SelfContentObserver hooked up to this Cursor
  76. */
  77. public synchronized IContentObserver getObserver() {
  78. if (mObserverBridge == null) {
  79. mObserverBridge = new SelfContentObserver(this);
  80. }
  81. return null;//mObserverBridge.getContentObserver(); //TODO nf fix this
  82. }
  83. @Override
  84. public int getCount() {
  85. return mCount;
  86. }
  87. @Override
  88. public boolean onMove(int oldPosition, int newPosition) {
  89. try {
  90. // Make sure we have the proper window
  91. if (mWindow != null) {
  92. if (newPosition < mWindow.getStartPosition() ||
  93. newPosition >= (mWindow.getStartPosition() + mWindow.getNumRows())) {
  94. mWindow = mBulkCursor.getWindow(newPosition);
  95. } else if (mWantsAllOnMoveCalls) {
  96. mBulkCursor.onMove(newPosition);
  97. }
  98. } else {
  99. mWindow = mBulkCursor.getWindow(newPosition);
  100. }
  101. } catch (RemoteException ex) {
  102. // We tried to get a window and failed
  103. Log.e(TAG, "Unable to get window because the remote process is dead");
  104. return false;
  105. }
  106. // Couldn't obtain a window, something is wrong
  107. if (mWindow == null) {
  108. return false;
  109. }
  110. return true;
  111. }
  112. @Override
  113. public void deactivate() {
  114. // This will call onInvalidated(), so make sure to do it before calling release,
  115. // which is what actually makes the data set invalid.
  116. super.deactivate();
  117. try {
  118. mBulkCursor.deactivate();
  119. } catch (RemoteException ex) {
  120. Log.w(TAG, "Remote process exception when deactivating");
  121. }
  122. mWindow = null;
  123. }
  124. @Override
  125. public void close() {
  126. super.close();
  127. try {
  128. mBulkCursor.close();
  129. } catch (RemoteException ex) {
  130. Log.w(TAG, "Remote process exception when closing");
  131. }
  132. mWindow = null;
  133. }
  134. @Override
  135. public boolean requery() {
  136. try {
  137. int oldCount = mCount;
  138. //TODO get the window from a pool somewhere to avoid creating the memory dealer
  139. mCount = mBulkCursor.requery(getObserver(), new CursorWindow(
  140. false /* the window will be accessed across processes */));
  141. if (mCount != -1) {
  142. mPos = -1;
  143. mWindow = null;
  144. // super.requery() will call onChanged. Do it here instead of relying on the
  145. // observer from the far side so that observers can see a correct value for mCount
  146. // when responding to onChanged.
  147. super.requery();
  148. return true;
  149. } else {
  150. deactivate();
  151. return false;
  152. }
  153. } catch (Exception ex) {
  154. Log.e(TAG, "Unable to requery because the remote process exception " + ex.getMessage());
  155. deactivate();
  156. return false;
  157. }
  158. }
  159. /**
  160. * @hide
  161. * @deprecated
  162. */
  163. @Override
  164. public boolean deleteRow() {
  165. try {
  166. boolean result = mBulkCursor.deleteRow(mPos);
  167. if (result != false) {
  168. // The window contains the old value, discard it
  169. mWindow = null;
  170. // Fix up the position
  171. mCount = mBulkCursor.count();
  172. if (mPos < mCount) {
  173. int oldPos = mPos;
  174. mPos = -1;
  175. moveToPosition(oldPos);
  176. } else {
  177. mPos = mCount;
  178. }
  179. // Send the change notification
  180. onChange(true);
  181. }
  182. return result;
  183. } catch (RemoteException ex) {
  184. Log.e(TAG, "Unable to delete row because the remote process is dead");
  185. return false;
  186. }
  187. }
  188. @Override
  189. public String[] getColumnNames() {
  190. if (mColumns == null) {
  191. try {
  192. mColumns = mBulkCursor.getColumnNames();
  193. } catch (RemoteException ex) {
  194. Log.e(TAG, "Unable to fetch column names because the remote process is dead");
  195. return null;
  196. }
  197. }
  198. return mColumns;
  199. }
  200. /**
  201. * @hide
  202. * @deprecated
  203. */
  204. @Override
  205. public boolean commitUpdates(Map<? extends Long,
  206. ? extends Map<String,Object>> additionalValues) {
  207. if (!supportsUpdates()) {
  208. Log.e(TAG, "commitUpdates not supported on this cursor, did you include the _id column?");
  209. return false;
  210. }
  211. synchronized(mUpdatedRows) {
  212. if (additionalValues != null) {
  213. mUpdatedRows.putAll(additionalValues);
  214. }
  215. if (mUpdatedRows.size() <= 0) {
  216. return false;
  217. }
  218. try {
  219. boolean result = mBulkCursor.updateRows(mUpdatedRows);
  220. if (result == true) {
  221. mUpdatedRows.clear();
  222. // Send the change notification
  223. onChange(true);
  224. }
  225. return result;
  226. } catch (RemoteException ex) {
  227. Log.e(TAG, "Unable to commit updates because the remote process is dead");
  228. return false;
  229. }
  230. }
  231. }
  232. @Override
  233. public Bundle getExtras() {
  234. try {
  235. return mBulkCursor.getExtras();
  236. } catch (RemoteException e) {
  237. // This should never happen because the system kills processes that are using remote
  238. // cursors when the provider process is killed.
  239. throw new RuntimeException(e);
  240. }
  241. }
  242. @Override
  243. public Bundle respond(Bundle extras) {
  244. try {
  245. return mBulkCursor.respond(extras);
  246. } catch (RemoteException e) {
  247. // the system kills processes that are using remote cursors when the provider process
  248. // is killed, but this can still happen if this is being called from the system process,
  249. // so, better to log and return an empty bundle.
  250. Log.w(TAG, "respond() threw RemoteException, returning an empty bundle.", e);
  251. return Bundle.EMPTY;
  252. }
  253. }
  254. @Override
  255. public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
  256. // TODO Auto-generated method stub
  257. }
  258. @Override
  259. public void registerContentObserver(ContentObserver observer) {
  260. // TODO Auto-generated method stub
  261. }
  262. @Override
  263. public void registerDataSetObserver(DataSetObserver observer) {
  264. // TODO Auto-generated method stub
  265. }
  266. @Override
  267. public void unregisterContentObserver(ContentObserver observer) {
  268. // TODO Auto-generated method stub
  269. }
  270. @Override
  271. public void unregisterDataSetObserver(DataSetObserver observer) {
  272. // TODO Auto-generated method stub
  273. }
  274. }