1
22
23 package com.liferay.portal.util;
24
25 import com.liferay.portal.kernel.dao.db.DB;
26 import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
27 import com.liferay.portal.kernel.dao.jdbc.DataAccess;
28 import com.liferay.portal.kernel.util.FileUtil;
29 import com.liferay.portal.kernel.util.MultiValueMap;
30 import com.liferay.portal.kernel.util.SerializableUtil;
31
32 import java.io.File;
33 import java.io.Serializable;
34
35 import java.sql.Connection;
36 import java.sql.DriverManager;
37 import java.sql.PreparedStatement;
38 import java.sql.ResultSet;
39
40 import java.util.Collection;
41 import java.util.HashSet;
42 import java.util.Set;
43
44
49 public class FileMultiValueMap<K extends Serializable, V extends Serializable>
50 extends MultiValueMap<K, V> {
51
52 public FileMultiValueMap() {
53 _fileName = FileUtil.createTempFileName();
54
55 try {
56 Class.forName("org.hsqldb.jdbcDriver");
57 }
58 catch (Exception e) {
59 throw new RuntimeException(e);
60 }
61
62 _createDatabase();
63 }
64
65 public void clear() {
66 try {
67 _deleteDatabase();
68 _createDatabase();
69 }
70 catch (Throwable t) {
71 throw new RuntimeException(t);
72 }
73 }
74
75 public boolean containsKey(Object key) {
76 int count = _getCount((K)key, null);
77
78 if (count > 0) {
79 return true;
80 }
81 else {
82 return false;
83 }
84 }
85
86 public boolean containsValue(Object value) {
87 int count = _getCount(null, (V)value);
88
89 if (count > 0) {
90 return true;
91 }
92 else {
93 return false;
94 }
95 }
96
97 public Set<V> getAll(Object key) {
98 Connection con = null;
99 PreparedStatement ps = null;
100 ResultSet rs = null;
101
102 Set<V> values = null;
103
104 try {
105 con = _getConnection();
106
107 ps = con.prepareStatement("SELECT value_ FROM Map WHERE key_ = ?");
108
109 ps.setBytes(1, SerializableUtil.serialize(key));
110
111 rs = ps.executeQuery();
112
113 while (rs.next()) {
114 if (values == null) {
115 values = new HashSet<V>();
116 }
117
118 V value = null;
119
120 value = (V)SerializableUtil.deserialize(rs.getBytes(_VALUE));
121
122 values.add(value);
123 }
124 }
125 catch (Exception e) {
126 throw new RuntimeException(e);
127 }
128 finally {
129 DataAccess.cleanUp(con, ps, rs);
130 }
131
132 return values;
133 }
134
135 public boolean isEmpty() {
136 int count = _getCount(null, null);
137
138 if (count == 0) {
139 return true;
140 }
141 else {
142 return false;
143 }
144 }
145
146 public Set<K> keySet() {
147 Connection con = null;
148 PreparedStatement ps = null;
149 ResultSet rs = null;
150
151 Set<K> keys = null;
152
153 try {
154 con = _getConnection();
155
156 ps = con.prepareStatement("SELECT DISTINCT (key_) FROM Map ");
157
158 rs = ps.executeQuery();
159
160 while (rs.next()) {
161 if (keys == null) {
162 keys = new HashSet<K>();
163 }
164
165 K key = null;
166
167 key = (K)SerializableUtil.deserialize(rs.getBytes(_KEY));
168
169 keys.add(key);
170 }
171 }
172 catch (Exception e) {
173 throw new RuntimeException(e);
174 }
175 finally {
176 DataAccess.cleanUp(con, ps, rs);
177 }
178
179 return keys;
180 }
181
182 public V put(K key, V value) {
183 if ((key == null) || (value == null)) {
184 return null;
185 }
186
187 if (_getCount(key, value) == 0) {
188 Connection con = null;
189 PreparedStatement ps = null;
190
191 try {
192 con = _getConnection();
193
194 ps = con.prepareStatement(
195 "INSERT INTO Map (key_, value_) values (?, ?)");
196
197 ps.setBytes(1, SerializableUtil.serialize(key));
198 ps.setBytes(2, SerializableUtil.serialize(value));
199
200 ps.execute();
201 }
202 catch (Exception e) {
203 throw new RuntimeException(e);
204 }
205 finally {
206 DataAccess.cleanUp(con, ps);
207 }
208 }
209
210 return value;
211 }
212
213 public Set<V> putAll(K key, Collection<? extends V> values) {
214 Set<V> curValues = getAll(key);
215
216 if ((values == null) || values.isEmpty()) {
217 return curValues;
218 }
219
220 if (curValues == null) {
221 values = new HashSet<V>();
222 }
223
224 for (V value: values) {
225 if (!curValues.contains(value)) {
226 curValues.add(value);
227
228 put(key, value);
229 }
230 }
231
232 return curValues;
233 }
234
235 public V remove(Object key) {
236 Connection con = null;
237 PreparedStatement ps = null;
238 ResultSet rs = null;
239
240 V firstValue = null;
241
242 try {
243 con = _getConnection();
244
245 ps = con.prepareStatement("SELECT value_ FROM Map WHERE key_ = ?");
246
247 ps.setBytes(1, SerializableUtil.serialize(key));
248
249 rs = ps.executeQuery();
250
251 if (rs.next()) {
252 firstValue = (V)SerializableUtil.deserialize(
253 rs.getBytes(_VALUE));
254 }
255 }
256 catch (Exception e) {
257 throw new RuntimeException(e);
258 }
259 finally {
260 DataAccess.cleanUp(con, ps, rs);
261 }
262
263 try {
264 con = _getConnection();
265
266 ps = con.prepareStatement("DELETE FROM Map WHERE key_ = ?");
267
268 ps.setBytes(1, SerializableUtil.serialize(key));
269
270 ps.execute();
271 }
272 catch (Exception e) {
273 throw new RuntimeException(e);
274 }
275 finally {
276 DataAccess.cleanUp(con, ps);
277 }
278
279 return firstValue;
280 }
281
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"),
313 new File(_fileName + ".log"),
314 new File(_fileName + ".data"),
315 new File(_fileName + ".backup")
316 };
317
318 for (File file : files) {
319 if (file.exists()) {
320 file.delete();
321 }
322 }
323 }
324
325 private Connection _getConnection() throws Exception {
326 return DriverManager.getConnection(
327 "jdbc:hsqldb:file:" + _fileName, "sa", "");
328 }
329
330 private int _getCount(K key, V value) {
331 Connection con = null;
332 PreparedStatement ps = null;
333 ResultSet rs = null;
334
335 try {
336 con = _getConnection();
337
338 String sql = "SELECT count(*) FROM Map ";
339
340 if ((key != null) && (value != null)) {
341 sql += "WHERE key_ = ? AND value_ = ?";
342
343 ps = con.prepareStatement(sql);
344
345 ps.setBytes(1, SerializableUtil.serialize(key));
346 ps.setBytes(2, SerializableUtil.serialize(value));
347 }
348 else if (key != null) {
349 sql += "WHERE key_ = ?";
350
351 ps = con.prepareStatement(sql);
352
353 ps.setBytes(1, SerializableUtil.serialize(key));
354 }
355 else if (value != null) {
356 sql += "WHERE value_ = ?";
357
358 ps = con.prepareStatement(sql);
359
360 ps.setBytes(1, SerializableUtil.serialize(value));
361 }
362 else {
363 ps = con.prepareStatement(sql);
364 }
365
366 rs = ps.executeQuery();
367
368 rs.next();
369
370 return rs.getInt(1);
371 }
372 catch (Exception e) {
373 throw new RuntimeException(e);
374 }
375 finally {
376 DataAccess.cleanUp(con, ps, rs);
377 }
378 }
379
380 private static final String _CREATE_SQL =
381 "CREATE TABLE Map (key_ BLOB not null, value_ BLOB not null, primary " +
382 "key (key_, value_))";
383
384 private static final String _KEY = "key_";
385
386 private static final String _VALUE = "value_";
387
388 private String _fileName;
389
390 }