tizen 2.4 release
[framework/web/wrt-commons.git] / modules / widget_interface_dao / dao / widget_interface_dao.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @author      Lukasz Marek (l.marek@samsung.com)
18  * @author      Jihoon Chung (jihoon.chung@samsung.com)
19  * @author      Janusz Majnert (j.majnert@samsung.com)
20  * @author      Kamil Lysik (k.lysik@samsung.com)
21  * @version     0.2
22  * @brief
23  */
24
25 #include <wrt-commons/widget-interface-dao/widget_interface_dao.h>
26
27 #include <string>
28 #include <sys/stat.h>
29 #include <unistd.h>
30
31 #include <db-util.h>
32 #include <dpl/assert.h>
33 #include <dpl/log/wrt_log.h>
34 #include <dpl/string.h>
35 #include <dpl/wrt-dao-ro/property_dao_read_only.h>
36 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
37 #include <dpl/wrt-dao-ro/WrtDatabase.h>
38 #include <dpl/wrt-dao-ro/widget_config.h>
39
40 namespace {
41 const char* const DATABASE_NAME = ".widget_interface.db";
42
43 //query strings
44 const char* const UPDATE_PROPERTIES = "update Properties set value=?, readonly=?, configxml=? where key=?";
45 const char* const INSERT_INTO_PROPERTIES = "insert into Properties (value, readonly, configxml, key) values (?, ?, ?, ?)";
46 const char* const DELETE_FROM_PROPERTIES_WHERE_KEY = "delete from Properties where key=?";
47 const char* const SELECT_VALUE = "select value from Properties where key=?";
48 const char* const DELETE_FROM_PROPERTIES = "delete from Properties";
49 const char* const DELETE_FROM_PROPERTIES_WHERE_READONLY = "delete from Properties where readonly=0";
50 const char* const SELECT_COUNT = "select count(*) from Properties";
51 const char* const SELECT_KEY = "select key from Properties order by key";
52 const char* const SELECT_READONLY = "select readonly from Properties where key=?";
53
54 } // anonymous namespace
55
56 #define CATCH_DATABASE_ERROR \
57     Catch(SQLiteDAOBase::Exception::DatabaseError) { \
58         ReThrow(WidgetInterfaceDAO::Exception::DatabaseError); \
59     }
60
61 namespace WidgetInterfaceDB {
62
63 WidgetInterfaceDAO::WidgetInterfaceDAO(WrtDB::DbWidgetHandle widgetHandle)
64 {
65     if (DB_UTIL_OK != db_util_open_with_options(
66                             databaseFileName(widgetHandle).c_str(),
67                             &m_databaseInterface,
68                             SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX,
69                             NULL)) {
70         WrtLogE("Cannot open database. %s", sqlite3_errmsg(m_databaseInterface));
71         ThrowMsg(WidgetInterfaceDAO::Exception::DatabaseError, "Cannot open database");
72     }
73 }
74
75 WidgetInterfaceDAO::~WidgetInterfaceDAO()
76 {
77 }
78
79 void WidgetInterfaceDAO::setItem(const std::string& key,
80                                  const std::string& value,
81                                  bool readOnly)
82 {
83     setItem(key, value, readOnly, false);
84 }
85
86 void WidgetInterfaceDAO::setItem(const std::string& key,
87                                  const std::string& value,
88                                  bool readOnly,
89                                  bool fromConfigXml)
90 {
91     bool keyExists = true;
92     bool rowReadOnly = false;
93     Try {
94         rowReadOnly = isReadOnly(key);
95     } Catch(Exception::InvalidArgumentException){
96         keyExists = false;
97     }
98     if (rowReadOnly) {
99         ThrowMsg(Exception::LocalStorageValueNoModifableException, "setItem fail");
100     }
101
102     const char* const query = keyExists ? UPDATE_PROPERTIES : INSERT_INTO_PROPERTIES;
103     sqlite3_stmt* stmt;
104     Try {
105         stmt = sqlPrepare(query);
106
107         sqlBind(stmt, 1, value.c_str());
108         sqlBind(stmt, 2, readOnly ? 1 : 0);
109         sqlBind(stmt, 3, fromConfigXml ? 1 : 0);
110         sqlBind(stmt, 4, key.c_str());
111     } CATCH_DATABASE_ERROR
112
113     int rv = sqlite3_step(stmt);
114     releaseStatement(stmt);
115
116     if (SQLITE_DONE != rv) {
117         WrtLogE("sqlite3_step error. %s", sqlite3_errmsg(m_databaseInterface));
118         ThrowMsg(WidgetInterfaceDAO::Exception::DatabaseError, "setItem fail");
119     }
120 }
121
122 void WidgetInterfaceDAO::removeItem(const std::string& key)
123 {
124     bool readOnly = false;
125     Try {
126         readOnly = isReadOnly(key);
127     } Catch(Exception::InvalidArgumentException){
128         //nothing to do
129         return;
130     }
131
132     if (readOnly) {
133         ThrowMsg(Exception::LocalStorageValueNoModifableException, "removeItem fail");
134     }
135
136     sqlite3_stmt* stmt;
137     Try {
138         stmt = sqlPrepare(DELETE_FROM_PROPERTIES_WHERE_KEY);
139         sqlBind(stmt, 1, key.c_str());
140     } CATCH_DATABASE_ERROR
141
142     int rv = sqlite3_step(stmt);
143     releaseStatement(stmt);
144
145     if (SQLITE_DONE != rv) {
146         WrtLogE("sqlite3_step error. %s", sqlite3_errmsg(m_databaseInterface));
147         ThrowMsg(WidgetInterfaceDAO::Exception::DatabaseError, "removeItem fail");
148     }
149 }
150
151 boost::optional<std::string> WidgetInterfaceDAO::getValue(
152     const std::string& key)
153 {
154     sqlite3_stmt* stmt;
155     Try {
156         stmt = sqlPrepare(SELECT_VALUE);
157         sqlBind(stmt, 1, key.c_str());
158     } CATCH_DATABASE_ERROR
159
160     boost::optional<std::string> value;
161     if (SQLITE_ROW == sqlite3_step(stmt)) {
162         const char* val =
163                 reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
164         if (val != NULL) {
165             value = val;
166         }
167     }
168     releaseStatement(stmt);
169
170     return value;
171 }
172
173 void WidgetInterfaceDAO::clear(bool removeReadOnly)
174 {
175     sqlite3_stmt* stmt = NULL;
176     Try {
177         if (removeReadOnly) {
178             stmt = sqlPrepare(DELETE_FROM_PROPERTIES);
179         } else {
180             stmt = sqlPrepare(DELETE_FROM_PROPERTIES_WHERE_READONLY);
181         }
182     } CATCH_DATABASE_ERROR
183
184     int rv = sqlite3_step(stmt);
185     releaseStatement(stmt);
186
187     if (SQLITE_DONE != rv) {
188         WrtLogE("sqlite3_step error. %s", sqlite3_errmsg(m_databaseInterface));
189         ThrowMsg(WidgetInterfaceDAO::Exception::DatabaseError, "clear fail");
190     }
191 }
192
193 size_t WidgetInterfaceDAO::getStorageSize()
194 {
195     sqlite3_stmt* stmt;
196     Try {
197         stmt = sqlPrepare(SELECT_COUNT);
198     } CATCH_DATABASE_ERROR
199
200     int size = 0;
201     if (SQLITE_ROW == sqlite3_step(stmt)) {
202         size = sqlite3_column_int(stmt, 0);
203     }
204
205     releaseStatement(stmt);
206
207     return size;
208 }
209
210 std::string WidgetInterfaceDAO::getKeyByIndex(size_t index)
211 {
212     if (index >= getStorageSize()) {
213             Throw(Exception::InvalidArgumentException);
214     }
215
216     sqlite3_stmt* stmt;
217     Try {
218         stmt = sqlPrepare(SELECT_KEY);
219     } CATCH_DATABASE_ERROR
220     for (unsigned int loop = 0; loop <= index; ++loop) {
221         if (sqlite3_step(stmt) != SQLITE_ROW) {
222             releaseStatement(stmt);
223             ThrowMsg(WidgetInterfaceDAO::Exception::DatabaseError,
224                             "getKeyByIndex fail");
225         }
226     }
227
228     const char* key = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
229
230     if (key == NULL) {
231         releaseStatement(stmt);
232         ThrowMsg(WidgetInterfaceDAO::Exception::DatabaseError,
233                         "Invalid key is returned");
234     }
235     std::string retval = key;
236     releaseStatement(stmt);
237     return retval;
238 }
239
240 std::string WidgetInterfaceDAO::databaseFileName(WrtDB::DbWidgetHandle widgetHandle)
241 {
242     using namespace WrtDB::WidgetConfig;
243
244     WrtDB::WrtDatabase::attachToThreadRO();
245     std::string filename;
246     Try {
247         WrtDB::WidgetDAOReadOnly widgetDAO(widgetHandle);
248         WrtDB::TizenPkgId pkgid = widgetDAO.getTizenPkgId();
249         filename = GetWidgetPersistentStoragePath(pkgid) + "/" + DATABASE_NAME;
250     } Catch(WrtDB::WidgetDAOReadOnly::Exception::DatabaseError) {
251         ReThrowMsg(WidgetInterfaceDAO::Exception::DatabaseError,
252                         "databaseFileName");
253     }
254     WrtDB::WrtDatabase::detachFromThread();
255     return filename;
256 }
257
258 bool WidgetInterfaceDAO::isReadOnly(const std::string& key)
259 {
260     sqlite3_stmt* stmt;
261     Try {
262         stmt = sqlPrepare(SELECT_READONLY);
263         sqlBind(stmt, 1, key.c_str());
264     } CATCH_DATABASE_ERROR
265
266     bool ret = false;
267     if (SQLITE_ROW == sqlite3_step(stmt)) {
268         ret = sqlite3_column_int(stmt, 0) ? true : false;
269     } else {
270         // If key doesn't exist, throw
271         releaseStatement(stmt);
272         Throw(Exception::InvalidArgumentException);
273     }
274     releaseStatement(stmt);
275     return ret;
276 }
277
278 } // namespace WidgetInterfaceDB