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