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