· 8 years ago · Dec 08, 2017, 03:56 AM
1package de.unistuttgart.ipvs.pmp.resourcegroups.database;
2
3import java.util.Map;
4import java.util.Map.Entry;
5import java.util.regex.Matcher;
6import java.util.regex.Pattern;
7
8import android.content.ContentValues;
9import android.content.Context;
10import android.database.Cursor;
11import android.database.sqlite.SQLiteDatabase;
12import android.os.RemoteException;
13import de.unistuttgart.ipvs.pmp.Log;
14import de.unistuttgart.ipvs.pmp.resource.privacylevel.BooleanPrivacyLevel;
15
16@SuppressWarnings("rawtypes")
17public class DatabaseConnectionImpl extends IDatabaseConnection.Stub {
18
19 private final String TABLE_NAME = "^[a-zA-Z0-9_]+$";
20 private static final String COLUMN_NAME = "^((id ){0,1}[a-z0-9_]+)$";
21 private static final String COLUMN_TYPE = "^[a-zA-Z0-9_\\s]+$";
22 private static final String TABLE_CONSTRAINTS = "^[a-zA-Z0-9_\\s]+$";
23
24 private String dbName;
25 private int dbVersion = 1;
26 private String appID;
27 private String exceptionMessage;
28
29 private Context context;
30 private DatabaseResource resource;
31 private DatabaseOpenHelper helper;
32 private SQLiteDatabase db;
33
34 private Cursor cursor;
35
36
37 public DatabaseConnectionImpl(Context context, DatabaseResource resource, String appIdentifier) {
38 this.context = context;
39 this.resource = resource;
40 this.appID = appIdentifier;
41
42 String[] appIdentSplit = this.appID.split("\\.");
43 String tmp = "";
44 for (String oneSplit : appIdentSplit) {
45 tmp = tmp + oneSplit;
46 }// TODO Allow access to other databases
47 this.dbName = tmp;
48 Log.v("Database name : " + this.dbName);
49 this.exceptionMessage = context.getResources().getString(R.string.unauthorized_action_exception);
50 }
51
52
53 private void closeCursor() {
54 if (this.cursor != null) {
55 this.cursor.close();
56 }
57 }
58
59
60 @Override
61 public boolean createTable(String tableName, Map columns, String tableConstraint) throws RemoteException {
62 if (isCreate()) {
63 if ("".equals(tableName.trim()) || columns == null) {
64 return false;
65 }
66 if (columns.isEmpty()) {
67 return false;
68 }
69
70 // Check the tableName
71 tableName = strip(tableName);
72 if (!Pattern.matches(this.TABLE_NAME, tableName)) {
73 Log.d("Table name '" + tableName + "' invalid. " + this.TABLE_NAME);
74 return false;
75 }
76
77 // Build a SQL Statement
78 String s = "";
79 String sql = "CREATE TABLE IF NOT EXISTS " + this.dbName + tableName + " (";
80 Pattern pColName = Pattern.compile(COLUMN_NAME, Pattern.CASE_INSENSITIVE);
81 Matcher m1 = pColName.matcher("");
82 Pattern pType = Pattern.compile(COLUMN_TYPE, Pattern.CASE_INSENSITIVE);
83 Matcher m2 = pType.matcher("");
84
85 // Check the column descriptions
86 for (Object obj : columns.entrySet()) {
87 Entry<String, String> e = (Entry<String, String>) obj;
88 if (m1.reset(strip(e.getKey())).find() && m2.reset(strip(e.getValue())).find()) {
89 s += strip(e.getKey()) + " " + strip(e.getValue()) + ", ";
90 }
91 }
92 if (tableConstraint != null) {
93 Pattern p = Pattern.compile(TABLE_CONSTRAINTS, Pattern.CASE_INSENSITIVE);
94 m1 = p.matcher(strip(tableConstraint));
95 if (m1.find()) {
96 s += strip(tableConstraint) + ")";
97 }
98 } else {
99 s = s.substring(0, s.length() - 2) + ")";
100 }
101 sql = sql + s;
102 closeCursor();
103 openDB();
104 Log.v("Executing Sql query: " + sql);
105 this.cursor = this.db.rawQuery(sql, null);
106
107 // TODO Check table's existence
108 // SELECT name FROM sqlite_master WHERE type='table' AND
109 // name='table_name';
110 if (this.cursor.getCount() > 0) {
111 return true;
112 } else {
113 return false;
114 }
115 }
116 return false;
117 }
118
119
120 @Override
121 public int delete(String table, String whereClause, String[] whereArgs) throws RemoteException {
122 if (isModify()) {
123 openDB();
124 return this.db.delete(dbName+table, whereClause, whereArgs);
125 } else {
126 RemoteException ex = new RemoteException();
127 ex.initCause(new UnauthorizedActionException(this.exceptionMessage));
128 throw ex;
129 }
130 }
131
132
133 private ContentValues getContentValues(Map values) {
134 if (values == null || values.isEmpty()) {
135 return null;
136 }
137 ContentValues cv = new ContentValues();
138 for (Object value : values.entrySet()) {
139 // TODO test if set is in right order??????????????????????????????
140 Entry e = (Entry) value;
141 cv.put(e.getKey().toString(), e.getValue().toString());
142 }
143 return cv;
144 }
145
146
147 @Override
148 public String[] getCurrentRow() throws RemoteException {
149 if (this.cursor == null || !isRead()) {
150 RemoteException ex = new RemoteException();
151 ex.initCause(new UnauthorizedActionException(this.exceptionMessage));
152 throw ex;
153 } else if (this.cursor.isAfterLast() || this.cursor.isBeforeFirst()) {
154 return null;
155 } else {
156 String[] row = new String[this.cursor.getColumnCount()];
157 for (int i = 0; i < this.cursor.getColumnCount(); i++) {
158 row[i] = this.cursor.getString(i);
159 }
160 return row;
161 }
162 }
163
164
165 @Override
166 public double getDouble(int column) throws RemoteException {
167 if (this.cursor == null || !isRead()) {
168 RemoteException ex = new RemoteException();
169 ex.initCause(new UnauthorizedActionException(this.exceptionMessage));
170 throw ex;
171 } else if (this.cursor.getColumnCount() <= column) {
172 RemoteException ex = new RemoteException();
173 ex.initCause(new IndexOutOfBoundsException());
174 throw ex;
175 } else {
176 return (this.cursor.getDouble(column));
177 }
178 }
179
180
181 @Override
182 public int getInteger(int column) throws RemoteException {
183 if (this.cursor == null || !isRead()) {
184 RemoteException ex = new RemoteException();
185 ex.initCause(new UnauthorizedActionException(this.exceptionMessage));
186 throw ex;
187 } else if (this.cursor.getColumnCount() <= column) {
188 RemoteException ex = new RemoteException();
189 ex.initCause(new IndexOutOfBoundsException());
190 throw ex;
191 } else {
192 return (this.cursor.getInt(column));
193 }
194 }
195
196
197 @Override
198 public String[] getRowAndNext() throws RemoteException {
199 if (this.cursor == null || !isRead()) {
200 RemoteException ex = new RemoteException();
201 ex.initCause(new UnauthorizedActionException(this.exceptionMessage));
202 throw ex;
203 } else if (this.cursor.isAfterLast() || this.cursor.isBeforeFirst()) {
204 return null;
205 } else {
206 String[] row = new String[this.cursor.getColumnCount()];
207 for (int i = 0; i < this.cursor.getColumnCount(); i++) {
208 row[i] = this.cursor.getString(i);
209 }
210 this.cursor.moveToNext();
211 return row;
212 }
213
214 }
215
216
217 @Override
218 public String[] getRowAt(int position) throws RemoteException {
219 if (this.cursor == null || !isRead()) {
220 RemoteException ex = new RemoteException();
221 ex.initCause(new UnauthorizedActionException(this.exceptionMessage));
222 throw ex;
223 } else if ((this.cursor.getCount() <= position) || (position < 0)) {
224 return null;
225 } else {
226 this.cursor.moveToPosition(position);
227 String[] row = new String[this.cursor.getColumnCount()];
228 for (int i = 0; i < this.cursor.getColumnCount(); i++) {
229 row[i] = this.cursor.getString(i);
230 }
231 return row;
232 }
233 }
234
235
236 @Override
237 public long getRowPosition() throws RemoteException {
238 if (this.cursor != null || !isRead()) {
239 return this.cursor.getPosition();
240 } else {
241 return -1;
242 }
243 }
244
245
246 @Override
247 public String getString(int column) throws RemoteException {
248 if (this.cursor == null || !isRead()) {
249 RemoteException ex = new RemoteException();
250 ex.initCause(new UnauthorizedActionException(this.exceptionMessage));
251 throw ex;
252 } else if (this.cursor.getColumnCount() <= column) {
253 RemoteException ex = new RemoteException();
254 ex.initCause(new IndexOutOfBoundsException());
255 throw ex;
256 } else {
257 return this.cursor.getString(column);
258 }
259 }
260
261
262 @Override
263 public boolean goToRowPosition(int position) throws RemoteException {
264 if (this.cursor == null || !isRead()) {
265 return false;
266 } else {
267 return this.cursor.moveToPosition(position);
268 }
269 }
270
271
272 @Override
273 public long insert(String table, String nullColumnHack, Map values) throws RemoteException {
274 if (isModify()) {
275 openDB();
276 return this.db.insert(dbName + table, nullColumnHack, getContentValues(values));
277 } else {
278 RemoteException ex = new RemoteException();
279 ex.initCause(new UnauthorizedActionException(this.exceptionMessage));
280 throw ex;
281 }
282 }
283
284
285 private boolean isCreate() {
286 return ((BooleanPrivacyLevel) this.resource.getPrivacyLevel(DatabaseResourceGroup.PRIVACY_LEVEL_CREATE))
287 .permits(this.appID, true);
288 }
289
290
291 private boolean isModify() {
292 return ((BooleanPrivacyLevel) this.resource.getPrivacyLevel(DatabaseResourceGroup.PRIVACY_LEVEL_MODIFY))
293 .permits(this.appID, true);
294 }
295
296
297 private boolean isRead() {
298 return ((BooleanPrivacyLevel) this.resource.getPrivacyLevel(DatabaseResourceGroup.PRIVACY_LEVEL_READ)).permits(
299 this.appID, true);
300 }
301
302
303 @Override
304 public boolean next() throws RemoteException {
305 if (this.cursor == null || !isRead()) {
306 return false;
307 } else {
308 return this.cursor.moveToNext();
309 }
310 }
311
312
313 private void openDB() {
314 if (this.db == null) {
315 // Open a database connection
316 if (this.helper == null) {
317 // TODO Feature: open other databases
318 this.helper = new DatabaseOpenHelper(this.context, this.dbName, this.dbVersion);
319 }
320 this.db = this.helper.getWritableDatabase();
321 }
322 }
323
324
325 @Override
326 public long query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy,
327 String having, String orderBy) throws RemoteException {
328 if (isRead()) {
329 closeCursor();
330 openDB();
331 this.cursor = this.db.query(dbName+table, columns, selection, selectionArgs, groupBy, having, orderBy);
332 this.cursor.moveToFirst();
333 return this.cursor.getCount();
334 } else {
335 RemoteException ex = new RemoteException();
336 ex.initCause(new UnauthorizedActionException(this.exceptionMessage));
337 throw ex;
338 }
339 }
340
341
342 @Override
343 public long queryWithLimit(String table, String[] columns, String selection, String[] selectionArgs,
344 String groupBy, String having, String orderBy, String limit) throws RemoteException {
345 if (isRead()) {
346 closeCursor();
347 openDB();
348 this.cursor = this.db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy, limit);
349 return this.cursor.getCount();
350 } else {
351 RemoteException ex = new RemoteException();
352 ex.initCause(new UnauthorizedActionException(this.exceptionMessage));
353 throw ex;
354 }
355 }
356
357
358 private String strip(String s) {
359 return s.trim().replaceAll("(\\s+)", " ");
360 }
361
362
363 @Override
364 public int update(String table, Map values, String whereClause, String[] whereArgs) throws RemoteException {
365 if (isModify()) {
366 openDB();
367 return this.db.update(dbName+table, getContentValues(values), whereClause, whereArgs);
368 } else {
369 RemoteException ex = new RemoteException();
370 ex.initCause(new UnauthorizedActionException(this.exceptionMessage));
371 throw ex;
372 }
373 }
374
375
376 @Override
377 public void close() throws RemoteException {
378 if (this.cursor != null) {
379 this.cursor.close();
380 this.cursor = null;
381 }
382 if (this.db != null) {
383 this.db.close();
384 this.db = null;
385 }
386 if (this.helper != null) {
387 this.helper.close();
388 this.helper = null;
389 }
390 }
391
392
393 @Override
394 public boolean deleteTable(String tableName) throws RemoteException {
395 if (isCreate()) {
396 if ("".equals(tableName.trim())) {
397 return false;
398 }
399
400 // Check the tableName
401 tableName = strip(tableName);
402 if (!Pattern.matches(this.TABLE_NAME, tableName)) {
403 Log.d("Table name '" + tableName + "' invalid. " + this.TABLE_NAME);
404 return false;
405 }
406
407 // Build a SQL Statement
408 String sql = "DROP TABLE IF EXISTS " + this.dbName + "." + tableName;
409 closeCursor();
410 openDB();
411 this.cursor = this.db.rawQuery(sql, null);
412
413 // TODO Check table's existence
414 // SELECT name FROM sqlite_master WHERE type='table' AND
415 // name='table_name';
416 if (this.cursor.getCount() >= 0) {
417 return true;
418 } else {
419 return false;
420 }
421 }
422 return false;
423 }
424}