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