Hidden NPE fixed, which appeared when someone pass null as arguments

(for such SQL as e.g. CREATE TABLE).

It is especially important when work with dome 3d party persistemce
libraries, like e.g. http://github.com/zefhemel/persistencejs which
passes these nulls.
This commit is contained in:
Roman 2011-03-25 16:46:26 +06:00 committed by Fil Maj
parent 674015460f
commit 887f754014

158
framework/src/com/phonegap/Storage.java Executable file → Normal file
View File

@ -16,15 +16,15 @@ import android.database.Cursor;
import android.database.sqlite.*; import android.database.sqlite.*;
/** /**
* This class implements the HTML5 database support for Android 1.X devices. * This class implements the HTML5 database support for Android 1.X devices. It
* It is not used for Android 2.X, since HTML5 database is built in to the browser. * is not used for Android 2.X, since HTML5 database is built in to the browser.
*/ */
public class Storage extends Plugin { public class Storage extends Plugin {
SQLiteDatabase myDb = null; // Database object SQLiteDatabase myDb = null; // Database object
String path = null; // Database path String path = null; // Database path
String dbName = null; // Database name String dbName = null; // Database name
/** /**
* Constructor. * Constructor.
*/ */
@ -34,29 +34,37 @@ public class Storage extends Plugin {
/** /**
* Executes the request and returns PluginResult. * Executes the request and returns PluginResult.
* *
* @param action The action to execute. * @param action
* @param args JSONArry of arguments for the plugin. * The action to execute.
* @param callbackId The callback id used when calling back into JavaScript. * @param args
* @return A PluginResult object with a status and message. * JSONArry of arguments for the plugin.
* @param callbackId
* The callback id used when calling back into JavaScript.
* @return A PluginResult object with a status and message.
*/ */
public PluginResult execute(String action, JSONArray args, String callbackId) { public PluginResult execute(String action, JSONArray args, String callbackId) {
PluginResult.Status status = PluginResult.Status.OK; PluginResult.Status status = PluginResult.Status.OK;
String result = ""; String result = "";
try { try {
// TODO: Do we want to allow a user to do this, since they could get to other app databases? // TODO: Do we want to allow a user to do this, since they could get
// to other app databases?
if (action.equals("setStorage")) { if (action.equals("setStorage")) {
this.setStorage(args.getString(0)); this.setStorage(args.getString(0));
} } else if (action.equals("openDatabase")) {
else if (action.equals("openDatabase")) { this.openDatabase(args.getString(0), args.getString(1),
this.openDatabase(args.getString(0), args.getString(1), args.getString(2), args.getLong(3)); args.getString(2), args.getLong(3));
} } else if (action.equals("executeSql")) {
else if (action.equals("executeSql")) { String[] s = null;
JSONArray a = args.getJSONArray(1); if (args.isNull(1)) {
int len = a.length(); s = new String[0];
String[] s = new String[len]; } else {
for (int i=0; i<len; i++) { JSONArray a = args.getJSONArray(1);
s[i] = a.getString(i); int len = a.length();
s = new String[len];
for (int i = 0; i < len; i++) {
s[i] = a.getString(i);
}
} }
this.executeSql(args.getString(0), s, args.getString(2)); this.executeSql(args.getString(0), s, args.getString(2));
} }
@ -67,15 +75,17 @@ public class Storage extends Plugin {
} }
/** /**
* Identifies if action to be executed returns a value and should be run synchronously. * Identifies if action to be executed returns a value and should be run
* synchronously.
* *
* @param action The action to execute * @param action
* @return T=returns value * The action to execute
* @return T=returns value
*/ */
public boolean isSynch(String action) { public boolean isSynch(String action) {
return false; return false;
} }
/** /**
* Clean up and close database. * Clean up and close database.
*/ */
@ -87,33 +97,40 @@ public class Storage extends Plugin {
} }
} }
//-------------------------------------------------------------------------- // --------------------------------------------------------------------------
// LOCAL METHODS // LOCAL METHODS
//-------------------------------------------------------------------------- // --------------------------------------------------------------------------
/** /**
* Set the application package for the database. Each application saves its * Set the application package for the database. Each application saves its
* database files in a directory with the application package as part of the file name. * database files in a directory with the application package as part of the
* file name.
* *
* For example, application "com.phonegap.demo.Demo" would save its database * For example, application "com.phonegap.demo.Demo" would save its database
* files in "/data/data/com.phonegap.demo/databases/" directory. * files in "/data/data/com.phonegap.demo/databases/" directory.
* *
* @param appPackage The application package. * @param appPackage
* The application package.
*/ */
public void setStorage(String appPackage) { public void setStorage(String appPackage) {
this.path = "/data/data/" + appPackage + "/databases/"; this.path = "/data/data/" + appPackage + "/databases/";
} }
/** /**
* Open database. * Open database.
* *
* @param db The name of the database * @param db
* @param version The version * The name of the database
* @param display_name The display name * @param version
* @param size The size in bytes * The version
* @param display_name
* The display name
* @param size
* The size in bytes
*/ */
public void openDatabase(String db, String version, String display_name, long size) { public void openDatabase(String db, String version, String display_name,
long size) {
// If database is open, then close it // If database is open, then close it
if (this.myDb != null) { if (this.myDb != null) {
this.myDb.close(); this.myDb.close();
@ -121,54 +138,60 @@ public class Storage extends Plugin {
// If no database path, generate from application package // If no database path, generate from application package
if (this.path == null) { if (this.path == null) {
Package pack = this.ctx.getClass().getPackage(); Package pack = this.ctx.getClass().getPackage();
String appPackage = pack.getName(); String appPackage = pack.getName();
this.setStorage(appPackage); this.setStorage(appPackage);
} }
this.dbName = this.path + db + ".db"; this.dbName = this.path + db + ".db";
this.myDb = SQLiteDatabase.openOrCreateDatabase(this.dbName, null); this.myDb = SQLiteDatabase.openOrCreateDatabase(this.dbName, null);
} }
/** /**
* Execute SQL statement. * Execute SQL statement.
* *
* @param query The SQL query * @param query
* @param params Parameters for the query * The SQL query
* @param tx_id Transaction id * @param params
* Parameters for the query
* @param tx_id
* Transaction id
*/ */
public void executeSql(String query, String[] params, String tx_id) { public void executeSql(String query, String[] params, String tx_id) {
try { try {
Cursor myCursor = this.myDb.rawQuery(query, params); Cursor myCursor = this.myDb.rawQuery(query, params);
this.processResults(myCursor, tx_id); this.processResults(myCursor, tx_id);
myCursor.close(); myCursor.close();
} } catch (SQLiteException ex) {
catch (SQLiteException ex) {
ex.printStackTrace(); ex.printStackTrace();
System.out.println("Storage.executeSql(): Error=" + ex.getMessage()); System.out
.println("Storage.executeSql(): Error=" + ex.getMessage());
// Send error message back to JavaScript // Send error message back to JavaScript
this.sendJavascript("droiddb.fail('" + ex.getMessage() + "','" + tx_id + "');"); this.sendJavascript("droiddb.fail('" + ex.getMessage() + "','"
+ tx_id + "');");
} }
} }
/** /**
* Process query results. * Process query results.
* *
* @param cur Cursor into query results * @param cur
* @param tx_id Transaction id * Cursor into query results
* @param tx_id
* Transaction id
*/ */
public void processResults(Cursor cur, String tx_id) { public void processResults(Cursor cur, String tx_id) {
String result = "[]"; String result = "[]";
// If query result has rows // If query result has rows
if (cur.moveToFirst()) { if (cur.moveToFirst()) {
JSONArray fullresult = new JSONArray(); JSONArray fullresult = new JSONArray();
String key = ""; String key = "";
String value = ""; String value = "";
int colCount = cur.getColumnCount(); int colCount = cur.getColumnCount();
// Build up JSON result object for each row // Build up JSON result object for each row
do { do {
JSONObject row = new JSONObject(); JSONObject row = new JSONObject();
@ -179,19 +202,20 @@ public class Storage extends Plugin {
row.put(key, value); row.put(key, value);
} }
fullresult.put(row); fullresult.put(row);
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
} }
} while (cur.moveToNext()); } while (cur.moveToNext());
result = fullresult.toString(); result = fullresult.toString();
} }
// Let JavaScript know that there are no more rows // Let JavaScript know that there are no more rows
this.sendJavascript("droiddb.completeQuery('" + tx_id + "', "+result+");"); this.sendJavascript("droiddb.completeQuery('" + tx_id + "', " + result
+ ");");
} }
} }