1 /* ownCloud Android client application
2 * Copyright (C) 2012 Bartek Przybylski
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 package eu
.alefzero
.owncloud
.datamodel
;
22 import java
.util
.ArrayList
;
23 import java
.util
.Collections
;
24 import java
.util
.Iterator
;
25 import java
.util
.List
;
26 import java
.util
.Vector
;
28 import eu
.alefzero
.owncloud
.db
.ProviderMeta
;
29 import eu
.alefzero
.owncloud
.db
.ProviderMeta
.ProviderTableMeta
;
30 import android
.accounts
.Account
;
31 import android
.content
.ContentProviderClient
;
32 import android
.content
.ContentProviderOperation
;
33 import android
.content
.ContentProviderResult
;
34 import android
.content
.ContentResolver
;
35 import android
.content
.ContentValues
;
36 import android
.content
.OperationApplicationException
;
37 import android
.database
.Cursor
;
38 import android
.net
.Uri
;
39 import android
.os
.Environment
;
40 import android
.os
.RemoteException
;
41 import android
.util
.Log
;
43 public class FileDataStorageManager
implements DataStorageManager
{
45 private ContentResolver mContentResolver
;
46 private ContentProviderClient mContentProvider
;
47 private Account mAccount
;
49 private static String TAG
= "FileDataStorageManager";
51 public FileDataStorageManager(Account account
, ContentResolver cr
) {
52 mContentProvider
= null
;
53 mContentResolver
= cr
;
57 public FileDataStorageManager(Account account
, ContentProviderClient cp
) {
58 mContentProvider
= cp
;
59 mContentResolver
= null
;
64 public OCFile
getFileByPath(String path
) {
65 Cursor c
= getCursorForValue(ProviderTableMeta
.FILE_PATH
, path
);
67 if (c
.moveToFirst()) {
68 file
= createFileInstance(c
);
75 public OCFile
getFileById(long id
) {
76 Cursor c
= getCursorForValue(ProviderTableMeta
._ID
, String
.valueOf(id
));
78 if (c
.moveToFirst()) {
79 file
= createFileInstance(c
);
86 public boolean fileExists(long id
) {
87 return fileExists(ProviderTableMeta
._ID
, String
.valueOf(id
));
91 public boolean fileExists(String path
) {
92 return fileExists(ProviderTableMeta
.FILE_PATH
, path
);
96 public boolean saveFile(OCFile file
) {
97 boolean overriden
= false
;
98 ContentValues cv
= new ContentValues();
99 cv
.put(ProviderTableMeta
.FILE_MODIFIED
, file
.getModificationTimestamp());
100 cv
.put(ProviderTableMeta
.FILE_CREATION
, file
.getCreationTimestamp());
101 cv
.put(ProviderTableMeta
.FILE_CONTENT_LENGTH
, file
.getFileLength());
102 cv
.put(ProviderTableMeta
.FILE_CONTENT_TYPE
, file
.getMimetype());
103 cv
.put(ProviderTableMeta
.FILE_NAME
, file
.getFileName());
104 if (file
.getParentId() != 0)
105 cv
.put(ProviderTableMeta
.FILE_PARENT
, file
.getParentId());
106 cv
.put(ProviderTableMeta
.FILE_PATH
, file
.getRemotePath());
107 if (!file
.isDirectory())
108 cv
.put(ProviderTableMeta
.FILE_STORAGE_PATH
, file
.getStoragePath());
109 cv
.put(ProviderTableMeta
.FILE_ACCOUNT_OWNER
, mAccount
.name
);
110 cv
.put(ProviderTableMeta
.FILE_LAST_SYNC_DATE
, file
.getLastSyncDate());
111 cv
.put(ProviderTableMeta
.FILE_KEEP_IN_SYNC
, file
.keepInSync() ?
1 : 0);
113 if (fileExists(file
.getRemotePath())) {
114 OCFile oldFile
= getFileByPath(file
.getRemotePath());
115 if (file
.getStoragePath() == null
&& oldFile
.getStoragePath() != null
)
116 file
.setStoragePath(oldFile
.getStoragePath());
117 if (!file
.isDirectory());
118 cv
.put(ProviderTableMeta
.FILE_STORAGE_PATH
, file
.getStoragePath());
119 file
.setFileId(oldFile
.getFileId());
122 if (getContentResolver() != null
) {
123 getContentResolver().update(ProviderTableMeta
.CONTENT_URI
, cv
,
124 ProviderTableMeta
._ID
+ "=?",
125 new String
[] { String
.valueOf(file
.getFileId()) });
128 getContentProvider().update(ProviderTableMeta
.CONTENT_URI
,
129 cv
, ProviderTableMeta
._ID
+ "=?",
130 new String
[] { String
.valueOf(file
.getFileId()) });
131 } catch (RemoteException e
) {
133 "Fail to insert insert file to database "
138 Uri result_uri
= null
;
139 if (getContentResolver() != null
) {
140 result_uri
= getContentResolver().insert(
141 ProviderTableMeta
.CONTENT_URI_FILE
, cv
);
144 result_uri
= getContentProvider().insert(
145 ProviderTableMeta
.CONTENT_URI_FILE
, cv
);
146 } catch (RemoteException e
) {
148 "Fail to insert insert file to database "
152 if (result_uri
!= null
) {
153 long new_id
= Long
.parseLong(result_uri
.getPathSegments()
155 file
.setFileId(new_id
);
159 if (file
.isDirectory() && file
.needsUpdatingWhileSaving())
160 for (OCFile f
: getDirectoryContent(file
))
168 public void saveFiles(List
<OCFile
> files
) {
170 Iterator
<OCFile
> filesIt
= files
.iterator();
171 ArrayList
<ContentProviderOperation
> operations
= new ArrayList
<ContentProviderOperation
>(files
.size());
174 // prepare operations to perform
175 while (filesIt
.hasNext()) {
176 file
= filesIt
.next();
177 ContentValues cv
= new ContentValues();
178 cv
.put(ProviderTableMeta
.FILE_MODIFIED
, file
.getModificationTimestamp());
179 cv
.put(ProviderTableMeta
.FILE_CREATION
, file
.getCreationTimestamp());
180 cv
.put(ProviderTableMeta
.FILE_CONTENT_LENGTH
, file
.getFileLength());
181 cv
.put(ProviderTableMeta
.FILE_CONTENT_TYPE
, file
.getMimetype());
182 cv
.put(ProviderTableMeta
.FILE_NAME
, file
.getFileName());
183 if (file
.getParentId() != 0)
184 cv
.put(ProviderTableMeta
.FILE_PARENT
, file
.getParentId());
185 cv
.put(ProviderTableMeta
.FILE_PATH
, file
.getRemotePath());
186 if (!file
.isDirectory())
187 cv
.put(ProviderTableMeta
.FILE_STORAGE_PATH
, file
.getStoragePath());
188 cv
.put(ProviderTableMeta
.FILE_ACCOUNT_OWNER
, mAccount
.name
);
189 cv
.put(ProviderTableMeta
.FILE_LAST_SYNC_DATE
, file
.getLastSyncDate());
190 cv
.put(ProviderTableMeta
.FILE_KEEP_IN_SYNC
, file
.keepInSync() ?
1 : 0);
192 if (fileExists(file
.getRemotePath())) {
193 OCFile tmpfile
= getFileByPath(file
.getRemotePath());
194 file
.setStoragePath(tmpfile
.getStoragePath());
195 if (!file
.isDirectory());
196 cv
.put(ProviderTableMeta
.FILE_STORAGE_PATH
, file
.getStoragePath());
197 file
.setFileId(tmpfile
.getFileId());
199 operations
.add(ContentProviderOperation
.newUpdate(ProviderTableMeta
.CONTENT_URI
).
201 withSelection( ProviderTableMeta
._ID
+ "=?",
202 new String
[] { String
.valueOf(file
.getFileId()) })
206 operations
.add(ContentProviderOperation
.newInsert(ProviderTableMeta
.CONTENT_URI
).withValues(cv
).build());
210 // apply operations in batch
211 ContentProviderResult
[] results
= null
;
213 if (getContentResolver() != null
) {
214 results
= getContentResolver().applyBatch(ProviderMeta
.AUTHORITY_FILES
, operations
);
217 results
= getContentProvider().applyBatch(operations
);
220 } catch (OperationApplicationException e
) {
221 Log
.e(TAG
, "Fail to update/insert list of files to database " + e
.getMessage());
223 } catch (RemoteException e
) {
224 Log
.e(TAG
, "Fail to update/insert list of files to database " + e
.getMessage());
227 // update new id in file objects for insertions
228 if (results
!= null
) {
230 for (int i
=0; i
<results
.length
; i
++) {
231 if (results
[i
].uri
!= null
) {
232 newId
= Long
.parseLong(results
[i
].uri
.getPathSegments().get(1));
233 files
.get(i
).setFileId(newId
);
234 //Log.v(TAG, "Found and added id in insertion for " + files.get(i).getRemotePath());
239 for (OCFile aFile
: files
) {
240 if (aFile
.isDirectory() && aFile
.needsUpdatingWhileSaving())
241 saveFiles(getDirectoryContent(aFile
));
246 public void setAccount(Account account
) {
250 public Account
getAccount() {
254 public void setContentResolver(ContentResolver cr
) {
255 mContentResolver
= cr
;
258 public ContentResolver
getContentResolver() {
259 return mContentResolver
;
262 public void setContentProvider(ContentProviderClient cp
) {
263 mContentProvider
= cp
;
266 public ContentProviderClient
getContentProvider() {
267 return mContentProvider
;
270 public Vector
<OCFile
> getDirectoryContent(OCFile f
) {
271 if (f
!= null
&& f
.isDirectory() && f
.getFileId() != -1) {
272 Vector
<OCFile
> ret
= new Vector
<OCFile
>();
274 Uri req_uri
= Uri
.withAppendedPath(
275 ProviderTableMeta
.CONTENT_URI_DIR
,
276 String
.valueOf(f
.getFileId()));
279 if (getContentProvider() != null
) {
281 c
= getContentProvider().query(req_uri
, null
,
282 ProviderTableMeta
.FILE_ACCOUNT_OWNER
+ "=?",
283 new String
[] { mAccount
.name
}, null
);
284 } catch (RemoteException e
) {
285 Log
.e(TAG
, e
.getMessage());
289 c
= getContentResolver().query(req_uri
, null
,
290 ProviderTableMeta
.FILE_ACCOUNT_OWNER
+ "=?",
291 new String
[] { mAccount
.name
}, null
);
294 if (c
.moveToFirst()) {
296 OCFile child
= createFileInstance(c
);
298 } while (c
.moveToNext());
303 Collections
.sort(ret
);
310 private boolean fileExists(String cmp_key
, String value
) {
312 if (getContentResolver() != null
) {
313 c
= getContentResolver()
314 .query(ProviderTableMeta
.CONTENT_URI
,
317 + ProviderTableMeta
.FILE_ACCOUNT_OWNER
319 new String
[] { value
, mAccount
.name
}, null
);
322 c
= getContentProvider().query(
323 ProviderTableMeta
.CONTENT_URI
,
326 + ProviderTableMeta
.FILE_ACCOUNT_OWNER
+ "=?",
327 new String
[] { value
, mAccount
.name
}, null
);
328 } catch (RemoteException e
) {
330 "Couldn't determine file existance, assuming non existance: "
335 boolean retval
= c
.moveToFirst();
340 private Cursor
getCursorForValue(String key
, String value
) {
342 if (getContentResolver() != null
) {
343 c
= getContentResolver()
344 .query(ProviderTableMeta
.CONTENT_URI
,
347 + ProviderTableMeta
.FILE_ACCOUNT_OWNER
349 new String
[] { value
, mAccount
.name
}, null
);
352 c
= getContentProvider().query(
353 ProviderTableMeta
.CONTENT_URI
,
355 key
+ "=? AND " + ProviderTableMeta
.FILE_ACCOUNT_OWNER
356 + "=?", new String
[] { value
, mAccount
.name
},
358 } catch (RemoteException e
) {
359 Log
.e(TAG
, "Could not get file details: " + e
.getMessage());
366 private OCFile
createFileInstance(Cursor c
) {
369 file
= new OCFile(c
.getString(c
370 .getColumnIndex(ProviderTableMeta
.FILE_PATH
)));
371 file
.setFileId(c
.getLong(c
.getColumnIndex(ProviderTableMeta
._ID
)));
372 file
.setParentId(c
.getLong(c
373 .getColumnIndex(ProviderTableMeta
.FILE_PARENT
)));
374 file
.setMimetype(c
.getString(c
375 .getColumnIndex(ProviderTableMeta
.FILE_CONTENT_TYPE
)));
376 if (!file
.isDirectory()) {
377 file
.setStoragePath(c
.getString(c
378 .getColumnIndex(ProviderTableMeta
.FILE_STORAGE_PATH
)));
379 if (file
.getStoragePath() == null
) {
380 // try to find existing file and bind it with current account
381 File sdCard
= Environment
.getExternalStorageDirectory();
382 File f
= new File(sdCard
.getAbsolutePath() + "/owncloud/" + mAccount
.name
+ file
.getRemotePath());
384 file
.setStoragePath(f
.getAbsolutePath());
387 file
.setFileLength(c
.getLong(c
388 .getColumnIndex(ProviderTableMeta
.FILE_CONTENT_LENGTH
)));
389 file
.setCreationTimestamp(c
.getLong(c
390 .getColumnIndex(ProviderTableMeta
.FILE_CREATION
)));
391 file
.setModificationTimestamp(c
.getLong(c
392 .getColumnIndex(ProviderTableMeta
.FILE_MODIFIED
)));
393 file
.setLastSyncDate(c
.getLong(c
394 .getColumnIndex(ProviderTableMeta
.FILE_LAST_SYNC_DATE
)));
395 file
.setKeepInSync(c
.getInt(
396 c
.getColumnIndex(ProviderTableMeta
.FILE_KEEP_IN_SYNC
)) == 1 ? true
: false
);
401 public void removeFile(OCFile file
) {
402 Uri file_uri
= Uri
.withAppendedPath(ProviderTableMeta
.CONTENT_URI_FILE
, ""+file
.getFileId());
403 if (getContentProvider() != null
) {
405 getContentProvider().delete(file_uri
,
406 ProviderTableMeta
.FILE_ACCOUNT_OWNER
+"=?",
407 new String
[]{mAccount
.name
});
408 } catch (RemoteException e
) {
412 getContentResolver().delete(file_uri
,
413 ProviderTableMeta
.FILE_ACCOUNT_OWNER
+"=?",
414 new String
[]{mAccount
.name
});
417 new File(file
.getStoragePath()).delete();