001
014
015 package com.liferay.portal.util;
016
017 import com.liferay.portal.kernel.dao.db.DB;
018 import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
019 import com.liferay.portal.kernel.dao.jdbc.DataAccess;
020 import com.liferay.portal.kernel.util.FileUtil;
021 import com.liferay.portal.kernel.util.MultiValueMap;
022 import com.liferay.util.SerializableUtil;
023
024 import java.io.File;
025 import java.io.Serializable;
026
027 import java.sql.Connection;
028 import java.sql.DriverManager;
029 import java.sql.PreparedStatement;
030 import java.sql.ResultSet;
031
032 import java.util.Collection;
033 import java.util.HashSet;
034 import java.util.Set;
035
036
039 public class FileMultiValueMap<K extends Serializable, V extends Serializable>
040 extends MultiValueMap<K, V> {
041
042 public FileMultiValueMap() {
043 _fileName = FileUtil.createTempFileName();
044
045 try {
046 Class.forName("org.hsqldb.jdbcDriver");
047 }
048 catch (Exception e) {
049 throw new RuntimeException(e);
050 }
051
052 _createDatabase();
053 }
054
055 @Override
056 public void clear() {
057 try {
058 _deleteDatabase();
059 _createDatabase();
060 }
061 catch (Throwable t) {
062 throw new RuntimeException(t);
063 }
064 }
065
066 @Override
067 public boolean containsKey(Object key) {
068 int count = _getCount((K)key, null);
069
070 if (count > 0) {
071 return true;
072 }
073 else {
074 return false;
075 }
076 }
077
078 @Override
079 public boolean containsValue(Object value) {
080 int count = _getCount(null, (V)value);
081
082 if (count > 0) {
083 return true;
084 }
085 else {
086 return false;
087 }
088 }
089
090 @Override
091 public Set<V> getAll(Object key) {
092 Connection con = null;
093 PreparedStatement ps = null;
094 ResultSet rs = null;
095
096 Set<V> values = null;
097
098 try {
099 con = _getConnection();
100
101 ps = con.prepareStatement("SELECT value_ FROM Map WHERE key_ = ?");
102
103 ps.setBytes(1, SerializableUtil.serialize(key));
104
105 rs = ps.executeQuery();
106
107 while (rs.next()) {
108 if (values == null) {
109 values = new HashSet<V>();
110 }
111
112 V value = null;
113
114 value = (V)SerializableUtil.deserialize(rs.getBytes(_VALUE));
115
116 values.add(value);
117 }
118 }
119 catch (Exception e) {
120 throw new RuntimeException(e);
121 }
122 finally {
123 DataAccess.cleanUp(con, ps, rs);
124 }
125
126 return values;
127 }
128
129 @Override
130 public boolean isEmpty() {
131 int count = _getCount(null, null);
132
133 if (count == 0) {
134 return true;
135 }
136 else {
137 return false;
138 }
139 }
140
141 @Override
142 public Set<K> keySet() {
143 Connection con = null;
144 PreparedStatement ps = null;
145 ResultSet rs = null;
146
147 Set<K> keys = null;
148
149 try {
150 con = _getConnection();
151
152 ps = con.prepareStatement("SELECT key_ FROM Map");
153
154 rs = ps.executeQuery();
155
156 while (rs.next()) {
157 if (keys == null) {
158 keys = new HashSet<K>();
159 }
160
161 K key = null;
162
163 key = (K)SerializableUtil.deserialize(rs.getBytes(_KEY));
164
165 keys.add(key);
166 }
167 }
168 catch (Exception e) {
169 throw new RuntimeException(e);
170 }
171 finally {
172 DataAccess.cleanUp(con, ps, rs);
173 }
174
175 return keys;
176 }
177
178 @Override
179 public V put(K key, V value) {
180 if ((key == null) || (value == null)) {
181 return null;
182 }
183
184 if (_getCount(key, value) == 0) {
185 Connection con = null;
186 PreparedStatement ps = null;
187
188 try {
189 con = _getConnection();
190
191 ps = con.prepareStatement(
192 "INSERT INTO Map (key_, value_) values (?, ?)");
193
194 ps.setBytes(1, SerializableUtil.serialize(key));
195 ps.setBytes(2, SerializableUtil.serialize(value));
196
197 ps.execute();
198 }
199 catch (Exception e) {
200 throw new RuntimeException(e);
201 }
202 finally {
203 DataAccess.cleanUp(con, ps);
204 }
205 }
206
207 return value;
208 }
209
210 @Override
211 public Set<V> putAll(K key, Collection<? extends V> values) {
212 Set<V> curValues = getAll(key);
213
214 if ((values == null) || values.isEmpty()) {
215 return curValues;
216 }
217
218 if (curValues == null) {
219 values = new HashSet<V>();
220 }
221
222 for (V value : values) {
223 if (!curValues.contains(value)) {
224 curValues.add(value);
225
226 put(key, value);
227 }
228 }
229
230 return curValues;
231 }
232
233 @Override
234 public V remove(Object key) {
235 Connection con = null;
236 PreparedStatement ps = null;
237 ResultSet rs = null;
238
239 V firstValue = null;
240
241 try {
242 con = _getConnection();
243
244 ps = con.prepareStatement("SELECT value_ FROM Map WHERE key_ = ?");
245
246 ps.setBytes(1, SerializableUtil.serialize(key));
247
248 rs = ps.executeQuery();
249
250 if (rs.next()) {
251 firstValue = (V)SerializableUtil.deserialize(
252 rs.getBytes(_VALUE));
253 }
254 }
255 catch (Exception e) {
256 throw new RuntimeException(e);
257 }
258 finally {
259 DataAccess.cleanUp(con, ps, rs);
260 }
261
262 try {
263 con = _getConnection();
264
265 ps = con.prepareStatement("DELETE FROM Map WHERE key_ = ?");
266
267 ps.setBytes(1, SerializableUtil.serialize(key));
268
269 ps.execute();
270 }
271 catch (Exception e) {
272 throw new RuntimeException(e);
273 }
274 finally {
275 DataAccess.cleanUp(con, ps);
276 }
277
278 return firstValue;
279 }
280
281 @Override
282 protected void finalize() throws Throwable {
283 try {
284 _deleteDatabase();
285 }
286 finally {
287 super.finalize();
288 }
289 }
290
291 private void _createDatabase() {
292 Connection con = null;
293
294 try {
295 con = _getConnection();
296
297 DB db = DBFactoryUtil.getDB(DB.TYPE_HYPERSONIC);
298
299 db.runSQL(con, _CREATE_SQL);
300 }
301 catch (Exception e) {
302 throw new RuntimeException(e);
303 }
304 finally {
305 DataAccess.cleanUp(con);
306 }
307 }
308
309 private void _deleteDatabase() throws Throwable {
310 File[] files = new File[] {
311 new File(_fileName + ".properties"),
312 new File(_fileName + ".script"), new File(_fileName + ".log"),
313 new File(_fileName + ".data"), new File(_fileName + ".backup")
314 };
315
316 for (File file : files) {
317 if (file.exists()) {
318 file.delete();
319 }
320 }
321 }
322
323 private Connection _getConnection() throws Exception {
324 return DriverManager.getConnection(
325 "jdbc:hsqldb:file:" + _fileName, "sa", "");
326 }
327
328 private int _getCount(K key, V value) {
329 Connection con = null;
330 PreparedStatement ps = null;
331 ResultSet rs = null;
332
333 try {
334 con = _getConnection();
335
336 String sql = "SELECT count(*) FROM Map ";
337
338 if ((key != null) && (value != null)) {
339 sql += "WHERE key_ = ? AND value_ = ?";
340
341 ps = con.prepareStatement(sql);
342
343 ps.setBytes(1, SerializableUtil.serialize(key));
344 ps.setBytes(2, SerializableUtil.serialize(value));
345 }
346 else if (key != null) {
347 sql += "WHERE key_ = ?";
348
349 ps = con.prepareStatement(sql);
350
351 ps.setBytes(1, SerializableUtil.serialize(key));
352 }
353 else if (value != null) {
354 sql += "WHERE value_ = ?";
355
356 ps = con.prepareStatement(sql);
357
358 ps.setBytes(1, SerializableUtil.serialize(value));
359 }
360 else {
361 ps = con.prepareStatement(sql);
362 }
363
364 rs = ps.executeQuery();
365
366 rs.next();
367
368 return rs.getInt(1);
369 }
370 catch (Exception e) {
371 throw new RuntimeException(e);
372 }
373 finally {
374 DataAccess.cleanUp(con, ps, rs);
375 }
376 }
377
378 private static final String _CREATE_SQL =
379 "CREATE TABLE Map (key_ BLOB not null, value_ BLOB not null)";
380
381 private static final String _KEY = "key_";
382
383 private static final String _VALUE = "value_";
384
385 private String _fileName;
386
387 }