/* * ServeStream: A HTTP stream browser/player for Android * Copyright 2013 William Seemann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.sourceforge.servestream.database; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import net.sourceforge.servestream.bean.UriBean; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; public class StreamDatabase extends SQLiteOpenHelper { public final static String TAG = StreamDatabase.class.getName(); public static final Object[] dbLock = new Object[0]; public static final String TABLE_STREAMS = "streams"; public static final String FIELD_STREAM_ID = "_id"; public static final String FIELD_STREAM_NICKNAME = "nickname"; public static final String FIELD_STREAM_PROTOCOL = "protocol"; public static final String FIELD_STREAM_USERNAME = "username"; public static final String FIELD_STREAM_PASSWORD = "password"; public static final String FIELD_STREAM_HOSTNAME = "hostname"; public static final String FIELD_STREAM_PORT = "port"; public static final String FIELD_STREAM_PATH = "path"; public static final String FIELD_STREAM_QUERY = "query"; public static final String FIELD_STREAM_REFERENCE = "reference"; public final static String FIELD_STREAM_LASTCONNECT = "lastconnect"; public final static String FIELD_STREAM_COLOR = "color"; public final static String FIELD_STREAM_FONTSIZE = "fontsize"; public final static String FIELD_STREAM_LIST_POSITION = "listposition"; public static final String DATABASE_NAME = "servestream.db"; private static final int DATABASE_VERSION = 5; private static final String STREAM_TABLE_CREATE = "CREATE TABLE " + TABLE_STREAMS + " (" + FIELD_STREAM_ID + " INTEGER PRIMARY KEY, " + FIELD_STREAM_NICKNAME + " TEXT, " + FIELD_STREAM_PROTOCOL + " TEXT, " + FIELD_STREAM_USERNAME + " TEXT, " + FIELD_STREAM_PASSWORD + " TEXT, " + FIELD_STREAM_HOSTNAME + " TEXT, " + FIELD_STREAM_PORT + " TEXT, " + FIELD_STREAM_PATH + " TEXT, " + FIELD_STREAM_QUERY + " TEXT, " + FIELD_STREAM_REFERENCE + " TEXT, " + FIELD_STREAM_LASTCONNECT + " INTEGER, " + FIELD_STREAM_COLOR + " TEXT, " + FIELD_STREAM_FONTSIZE + " INTEGER, " + FIELD_STREAM_LIST_POSITION + " INTEGER);"; public StreamDatabase(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); this.getWritableDatabase().close(); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(STREAM_TABLE_CREATE); Log.v(TAG, "new table created"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { try { onRobustUpgrade(db, oldVersion, newVersion); } catch (SQLiteException e) { // The database has entered an unknown state. Try to recover. try { //regenerateTables(db); } catch (SQLiteException e2) { //dropAndCreateTables(db); } } } public void onRobustUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) throws SQLiteException { if (oldVersion <= 2) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_STREAMS); onCreate(db); } switch (oldVersion) { case 3: db.execSQL("ALTER TABLE " + TABLE_STREAMS + " ADD COLUMN " + FIELD_STREAM_REFERENCE + " TEXT DEFAULT ''"); break; case 4: db.execSQL("ALTER TABLE " + TABLE_STREAMS + " ADD COLUMN " + FIELD_STREAM_LIST_POSITION + " INTEGER"); Cursor c = db.query(TABLE_STREAMS, null, null, null, null, null, FIELD_STREAM_ID + " ASC"); List<UriBean> uris = createUriBeans(c); c.close(); ContentValues values = new ContentValues(); for (int i = 0; i < uris.size(); i++) { UriBean uri = uris.get(i); values.clear(); values.put(StreamDatabase.FIELD_STREAM_LIST_POSITION, uri.getId()); db.update(TABLE_STREAMS, values, FIELD_STREAM_ID + " = ?", new String [] { String.valueOf(uri.getId()) }); } break; } } /** * Touch a specific stream to update its "last connected" field. * * @param stream Nickname field of stream to update */ public void touchUri(UriBean uri) { long now = System.currentTimeMillis() / 1000; ContentValues values = new ContentValues(); values.put(FIELD_STREAM_LASTCONNECT, now); synchronized (dbLock) { SQLiteDatabase db = this.getWritableDatabase(); db.update(TABLE_STREAMS, values, FIELD_STREAM_ID + " = ?", new String[] { String.valueOf(uri.getId()) }); } } /** * Touch a specific stream to update its "last connected" field. * * @param stream Nickname field of stream to update */ public void updateUri(UriBean uri, ContentValues values) { synchronized (dbLock) { SQLiteDatabase db = this.getWritableDatabase(); db.update(TABLE_STREAMS, values, FIELD_STREAM_ID + " = ?", new String[] { String.valueOf(uri.getId()) }); } } private List<UriBean> createUriBeans(Cursor c) { List<UriBean> uris = new ArrayList<UriBean>(); final int COL_ID = c.getColumnIndexOrThrow(FIELD_STREAM_ID), COL_NICKNAME = c.getColumnIndexOrThrow(FIELD_STREAM_NICKNAME), COL_PROTOCOL = c.getColumnIndexOrThrow(FIELD_STREAM_PROTOCOL), COL_USERNAME = c.getColumnIndexOrThrow(FIELD_STREAM_USERNAME), COL_PASSWORD = c.getColumnIndexOrThrow(FIELD_STREAM_PASSWORD), COL_HOST = c.getColumnIndexOrThrow(FIELD_STREAM_HOSTNAME), COL_PORT = c.getColumnIndexOrThrow(FIELD_STREAM_PORT), COL_PATH = c.getColumnIndexOrThrow(FIELD_STREAM_PATH), COL_QUERY = c.getColumnIndexOrThrow(FIELD_STREAM_QUERY), COL_REFERENCE = c.getColumnIndexOrThrow(FIELD_STREAM_REFERENCE), COL_LASTCONNECT = c.getColumnIndexOrThrow(FIELD_STREAM_LASTCONNECT), COL_LISTPOSITION = c.getColumnIndexOrThrow(FIELD_STREAM_LIST_POSITION); while (c.moveToNext()) { UriBean uri = new UriBean(); uri.setId(c.getLong(COL_ID)); uri.setNickname(c.getString(COL_NICKNAME)); uri.setProtocol(c.getString(COL_PROTOCOL)); uri.setUsername(c.getString(COL_USERNAME)); uri.setPassword(c.getString(COL_PASSWORD)); uri.setHostname(c.getString(COL_HOST)); uri.setPort(Integer.valueOf(c.getString(COL_PORT))); uri.setPath(c.getString(COL_PATH)); uri.setQuery(c.getString(COL_QUERY)); uri.setReference(c.getString(COL_REFERENCE)); uri.setLastConnect(c.getLong(COL_LASTCONNECT)); uri.setListPosition(c.getInt(COL_LISTPOSITION)); uris.add(uri); } return uris; } public List<UriBean> getUris() { List<UriBean> uris = new ArrayList<UriBean>(); synchronized (dbLock) { SQLiteDatabase db = this.getWritableDatabase(); Cursor c = db.query(TABLE_STREAMS, null, null, null, null, null, FIELD_STREAM_LIST_POSITION + " ASC"); uris = createUriBeans(c); c.close(); } return uris; } public void deleteUri(UriBean uri) { if (uri.getId() < 0) { return; } synchronized (dbLock) { SQLiteDatabase db = this.getWritableDatabase(); db.delete(TABLE_STREAMS, FIELD_STREAM_ID + " = ?", new String[] { String.valueOf(uri.getId()) }); } } public UriBean findUri(Map<String, String> selection) { StringBuffer sb = new StringBuffer(); sb.append("SELECT * from ") .append(TABLE_STREAMS) .append(" where "); ArrayList<String> selectionValuesList = new ArrayList<String>(); Iterator<Entry<String, String>> i = selection.entrySet().iterator(); int n = 0; while(i.hasNext()) { Entry<String, String> entry = i.next(); if (n++ > 0) sb.append(" AND "); sb.append(entry.getKey()); if (entry.getValue() == null) { sb.append(" IS NULL"); } else { selectionValuesList.add(entry.getValue()); sb.append(" = ?"); } } String selectionValues[] = new String[selectionValuesList.size()]; selectionValuesList.toArray(selectionValues); selectionValuesList = null; UriBean uri; synchronized (dbLock) { SQLiteDatabase db = getReadableDatabase(); Cursor c = db.rawQuery(sb.toString(), selectionValues); uri = getFirstUriBean(c); } return uri; } public UriBean findUri(int id) { UriBean uri; synchronized (dbLock) { SQLiteDatabase db = getReadableDatabase(); Cursor c = db.query(TABLE_STREAMS, null, FIELD_STREAM_ID + " = ?", new String[] { String.valueOf(id) }, null, null, null); uri = getFirstUriBean(c); } return uri; } private UriBean getFirstUriBean(Cursor c) { UriBean uri = null; List<UriBean> uris = createUriBeans(c); if (uris.size() > 0) uri = uris.get(0); c.close(); return uri; } public UriBean saveUri(UriBean uri) { long id; synchronized (dbLock) { SQLiteDatabase db = this.getWritableDatabase(); id = db.insert(TABLE_STREAMS, null, uri.getValues()); ContentValues values = new ContentValues(); values.put(StreamDatabase.FIELD_STREAM_LIST_POSITION, id); db.update(TABLE_STREAMS, values, FIELD_STREAM_ID + " = ?", new String [] { String.valueOf(id) }); } uri.setId(id); uri.setListPosition((int) id); Log.v("TAG", "Uri wrote to database"); return uri; } }