package org.sana.android.db; import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashMap; import org.sana.android.db.SanaDB.BinarySQLFormat; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.os.ParcelFileDescriptor; import android.text.TextUtils; import android.util.Log; /** * Content provider for binary file content. * * @author Sana Development Team * */ public class BinaryProvider extends ContentProvider { public static final String TAG = BinaryProvider.class.getSimpleName(); protected static final String TABLE = "binaries"; protected static final String[] PROJ_ITEM_CONTENT = new String[]{ BinarySQLFormat.CONTENT }; protected static final String[] PROJ_ID_AND_CONTENT = new String[]{ BinarySQLFormat._ID, BinarySQLFormat.CONTENT }; protected static final String OBS_WHERE = BinarySQLFormat.ENCOUNTER_ID + " = ? AND " + BinarySQLFormat.ELEMENT_ID +" = ?" ; protected static final String[] PROJ_ID = new String[]{ BinarySQLFormat._ID }; private static final int ITEMS = 1; private static final int ITEM_ID = 2; private DatabaseHelper mOpenHelper; private static final UriMatcher sUriMatcher; private static HashMap<String,String> sProjectionMap; /** {@inheritDoc} */ @Override public boolean onCreate() { Log.i(TAG, "onCreate()"); mOpenHelper = new DatabaseHelper(getContext()); return true; } private String getFileUriString(Uri uri){ String fUri = null; Cursor c = null; try{ c = query(uri, PROJ_ITEM_CONTENT, null, null, null); if(c.moveToFirst()){ int fColumn = c.getColumnIndex(BinarySQLFormat.CONTENT); fUri = c.getString(fColumn); } } finally { if(c != null) c.close(); } return fUri; } private Uri getItemContentUri(Uri uri){ String fUri = getFileUriString(uri); return (TextUtils.isEmpty(fUri))? null: Uri.parse(fUri); } /** {@inheritDoc} */ @Override public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { Uri fUri = null; String fString = null; try{ fUri = getItemContentUri(uri); Log.i(TAG, "openFile() for file uri: " + fUri); return getContext().getContentResolver().openFileDescriptor(fUri, mode); } catch (FileNotFoundException e){ Log.e(TAG, "File not found: " + fString); throw e; } catch (Exception e){ throw new FileNotFoundException(e.getMessage() + ":" + fString); } } /** {@inheritDoc} */ @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Log.i(TAG, "query() uri="+uri.toString() + " projection=" + TextUtils.join(",",projection)); SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); qb.setTables(TABLE); switch(sUriMatcher.match(uri)) { case ITEMS: break; case ITEM_ID: qb.appendWhere(BinarySQLFormat._ID + "=" + uri.getPathSegments().get(1)); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } String orderBy; if(TextUtils.isEmpty(sortOrder)) { orderBy = BinarySQLFormat.DEFAULT_SORT_ORDER; } else { orderBy = sortOrder; } SQLiteDatabase db = mOpenHelper.getReadableDatabase(); Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy); c.setNotificationUri(getContext().getContentResolver(), uri); return c; } /** {@inheritDoc} */ @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); int count = 0; switch(sUriMatcher.match(uri)) { case ITEMS: count = db.update(TABLE, values,selection,selectionArgs); break; case ITEM_ID: String procedureId = uri.getPathSegments().get(1); count = db.update(TABLE, values, BinarySQLFormat._ID + "=" + procedureId + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : ""), selectionArgs); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } /** {@inheritDoc} */ @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); Log.d(TAG, "Content uri: " + BinarySQLFormat.CONTENT_URI); Log.d(TAG, "Args: " + selectionArgs); Log.d(TAG, "Selection: " + selection); int count; switch (sUriMatcher.match(uri)) { case ITEMS: Cursor c = null; c = query(BinarySQLFormat.CONTENT_URI, new String[]{ BinarySQLFormat._ID, BinarySQLFormat.CONTENT }, selection, selectionArgs, null); if(c.moveToFirst()) { while(!c.isAfterLast()) { String u = null; long id = 0; id = c.getLong(c.getColumnIndex(BinarySQLFormat._ID)); u = c.getString(c.getColumnIndex( BinarySQLFormat.CONTENT)); Log.d(TAG, "Deleting: " + id); Log.d(TAG, "Deleting: " + u); Uri fUri = Uri.parse(u); Log.d(TAG, "Deleting: " + fUri); if(fUri != null) try{ getContext().getContentResolver().delete(fUri, null,null); } catch(Exception e){ Log.e(TAG, e.getMessage()); } c.moveToNext(); } } if(c != null) c.close(); count = db.delete(TABLE, selection, selectionArgs); break; case ITEM_ID: String binId = uri.getPathSegments().get(1); Uri fUri = getItemContentUri(uri); getContext().getContentResolver().delete(fUri, null,null); count = db.delete(TABLE, BinarySQLFormat._ID + "=" + binId + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : ""), selectionArgs); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } /** {@inheritDoc} */ @Override public Uri insert(Uri uri, ContentValues initialValues) { if (sUriMatcher.match(uri) != ITEMS) { throw new IllegalArgumentException("Unknown URI " + uri); } ContentValues values; if(initialValues != null) { values = new ContentValues(initialValues); } else { values = new ContentValues(); } Long now = Long.valueOf(System.currentTimeMillis()); if(values.containsKey(BinarySQLFormat.CREATED_DATE) == false) { values.put(BinarySQLFormat.CREATED_DATE, now); } if(values.containsKey(BinarySQLFormat.MODIFIED_DATE) == false) { values.put(BinarySQLFormat.MODIFIED_DATE, now); } if(values.containsKey(BinarySQLFormat.ENCOUNTER_ID) == false) { values.put(BinarySQLFormat.ENCOUNTER_ID, ""); } if(values.containsKey(BinarySQLFormat.UPLOAD_PROGRESS) == false) { values.put(BinarySQLFormat.UPLOAD_PROGRESS, 0); } if(values.containsKey(BinarySQLFormat.UPLOADED) == false) { values.put(BinarySQLFormat.UPLOADED, false); } if(values.containsKey(BinarySQLFormat.ELEMENT_ID) == false) { values.put(BinarySQLFormat.ELEMENT_ID, ""); } if(values.containsKey(BinarySQLFormat.CONTENT) == false) { values.put(BinarySQLFormat.CONTENT, ""); } if(values.containsKey(BinarySQLFormat.MIME) == false) { values.put(BinarySQLFormat.MIME, "application/octet-stream"); } // Defaults to empty string for file path if(values.containsKey(BinarySQLFormat.DATA) == false) { values.put(BinarySQLFormat.DATA, ""); } SQLiteDatabase db = mOpenHelper.getWritableDatabase(); long rowId = db.insert(TABLE, BinarySQLFormat.ENCOUNTER_ID, values); if(rowId > 0) { String filename = rowId + ""; try { getContext().openFileOutput(filename, Context.MODE_PRIVATE).close(); } catch (FileNotFoundException e) { Log.e(TAG, "Couldn't make the file: " + e); } catch (IOException e) { Log.e(TAG, "Couldn't make the file: " + e); } String path = getContext().getFileStreamPath(filename).getAbsolutePath(); Log.i(TAG, "File path is : " + path); Uri noteUri = ContentUris.withAppendedId(BinarySQLFormat.CONTENT_URI, rowId); getContext().getContentResolver().notifyChange(noteUri, null); return noteUri; } throw new SQLException("Failed to insert row into " + uri); } /** {@inheritDoc} */ @Override public String getType(Uri uri) { Log.i(TAG, "getType(uri="+uri.toString()+")"); switch(sUriMatcher.match(uri)) { case ITEMS: return BinarySQLFormat.CONTENT_TYPE; case ITEM_ID: return BinarySQLFormat.CONTENT_ITEM_TYPE; default: throw new IllegalArgumentException("Unknown URI " + uri); } } /** * Creates the table. * @param db the database to create the table in. */ public static void onCreateDatabase(SQLiteDatabase db) { Log.i(TAG, "Creating Binary Table"); db.execSQL("CREATE TABLE " + TABLE + " (" + BinarySQLFormat._ID + " INTEGER PRIMARY KEY," + BinarySQLFormat.ENCOUNTER_ID + " TEXT," + BinarySQLFormat.ELEMENT_ID + " TEXT," + BinarySQLFormat.UPLOAD_PROGRESS + " INTEGER," + BinarySQLFormat.UPLOADED + " INTEGER," + BinarySQLFormat.CREATED_DATE + " INTEGER," + BinarySQLFormat.MODIFIED_DATE + " INTEGER," + BinarySQLFormat.CONTENT + " TEXT," + BinarySQLFormat.MIME + " TEXT," + BinarySQLFormat.DATA + " TEXT" + ");"); } /** * Updates this providers table * @param db the db to update in * @param oldVersion the current db version * @param newVersion the new db version */ public static void onUpgradeDatabase(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion); // BinaryProvider only shows up in version 3 or higher if(oldVersion <= 2){ db.execSQL("DROP TABLE IF EXISTS " + TABLE); } onCreateDatabase(db); } static { sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); sUriMatcher.addURI(SanaDB.BINARY_AUTHORITY, TABLE, ITEMS); sUriMatcher.addURI(SanaDB.BINARY_AUTHORITY, TABLE+"/#", ITEM_ID); sProjectionMap = new HashMap<String, String>(); sProjectionMap.put(BinarySQLFormat._ID, BinarySQLFormat._ID); sProjectionMap.put(BinarySQLFormat.ELEMENT_ID, BinarySQLFormat.ELEMENT_ID); sProjectionMap.put(BinarySQLFormat.ENCOUNTER_ID, BinarySQLFormat.ENCOUNTER_ID); sProjectionMap.put(BinarySQLFormat.UPLOADED, BinarySQLFormat.UPLOADED); sProjectionMap.put(BinarySQLFormat.UPLOAD_PROGRESS, BinarySQLFormat.UPLOAD_PROGRESS); sProjectionMap.put(BinarySQLFormat.CREATED_DATE, BinarySQLFormat.CREATED_DATE); sProjectionMap.put(BinarySQLFormat.MODIFIED_DATE, BinarySQLFormat.MODIFIED_DATE); sProjectionMap.put(BinarySQLFormat.CONTENT, BinarySQLFormat.CONTENT); sProjectionMap.put(BinarySQLFormat.MIME, BinarySQLFormat.MIME); sProjectionMap.put(BinarySQLFormat.CONTENT, BinarySQLFormat.CONTENT); } }