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
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 HypersonicUtil.getInstance().runSQL(con, _CREATE_SQL);
298 }
299 catch (Exception e) {
300 throw new RuntimeException(e);
301 }
302 finally {
303 DataAccess.cleanUp(con);
304 }
305 }
306
307 private void _deleteDatabase() throws Throwable {
308 File[] files = new File[] {
309 new File(_fileName + ".properties"),
310 new File(_fileName + ".script"),
311 new File(_fileName + ".log"),
312 new File(_fileName + ".data"),
313 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, primary " +
380 "key (key_, value_))";
381
382 private static final String _KEY = "key_";
383
384 private static final String _VALUE = "value_";
385
386 private String _fileName;
387
388 }