001
014
015 package com.liferay.portal.util;
016
017 import com.liferay.portal.kernel.dao.db.DB;
018 import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
019 import com.liferay.portal.kernel.dao.jdbc.DataAccess;
020 import com.liferay.portal.kernel.util.FileUtil;
021 import com.liferay.portal.kernel.util.MultiValueMap;
022 import com.liferay.util.SerializableUtil;
023
024 import java.io.File;
025 import java.io.Serializable;
026
027 import java.sql.Connection;
028 import java.sql.DriverManager;
029 import java.sql.PreparedStatement;
030 import java.sql.ResultSet;
031
032 import java.util.Collection;
033 import java.util.HashSet;
034 import java.util.Set;
035
036
039 public class FileMultiValueMap<K extends Serializable, V extends Serializable>
040 extends MultiValueMap<K, V> {
041
042 public FileMultiValueMap() {
043 _fileName = FileUtil.createTempFileName();
044
045 try {
046 Class.forName("org.hsqldb.jdbcDriver");
047 }
048 catch (Exception e) {
049 throw new RuntimeException(e);
050 }
051
052 _createDatabase();
053 }
054
055 public void clear() {
056 try {
057 _deleteDatabase();
058 _createDatabase();
059 }
060 catch (Throwable t) {
061 throw new RuntimeException(t);
062 }
063 }
064
065 public boolean containsKey(Object key) {
066 int count = _getCount((K)key, null);
067
068 if (count > 0) {
069 return true;
070 }
071 else {
072 return false;
073 }
074 }
075
076 public boolean containsValue(Object value) {
077 int count = _getCount(null, (V)value);
078
079 if (count > 0) {
080 return true;
081 }
082 else {
083 return false;
084 }
085 }
086
087 @Override
088 public Set<V> getAll(Object key) {
089 Connection con = null;
090 PreparedStatement ps = null;
091 ResultSet rs = null;
092
093 Set<V> values = null;
094
095 try {
096 con = _getConnection();
097
098 ps = con.prepareStatement("SELECT value_ FROM Map WHERE key_ = ?");
099
100 ps.setBytes(1, SerializableUtil.serialize(key));
101
102 rs = ps.executeQuery();
103
104 while (rs.next()) {
105 if (values == null) {
106 values = new HashSet<V>();
107 }
108
109 V value = null;
110
111 value = (V)SerializableUtil.deserialize(rs.getBytes(_VALUE));
112
113 values.add(value);
114 }
115 }
116 catch (Exception e) {
117 throw new RuntimeException(e);
118 }
119 finally {
120 DataAccess.cleanUp(con, ps, rs);
121 }
122
123 return values;
124 }
125
126 public boolean isEmpty() {
127 int count = _getCount(null, null);
128
129 if (count == 0) {
130 return true;
131 }
132 else {
133 return false;
134 }
135 }
136
137 public Set<K> keySet() {
138 Connection con = null;
139 PreparedStatement ps = null;
140 ResultSet rs = null;
141
142 Set<K> keys = null;
143
144 try {
145 con = _getConnection();
146
147 ps = con.prepareStatement("SELECT key_ FROM Map");
148
149 rs = ps.executeQuery();
150
151 while (rs.next()) {
152 if (keys == null) {
153 keys = new HashSet<K>();
154 }
155
156 K key = null;
157
158 key = (K)SerializableUtil.deserialize(rs.getBytes(_KEY));
159
160 keys.add(key);
161 }
162 }
163 catch (Exception e) {
164 throw new RuntimeException(e);
165 }
166 finally {
167 DataAccess.cleanUp(con, ps, rs);
168 }
169
170 return keys;
171 }
172
173 public V put(K key, V value) {
174 if ((key == null) || (value == null)) {
175 return null;
176 }
177
178 if (_getCount(key, value) == 0) {
179 Connection con = null;
180 PreparedStatement ps = null;
181
182 try {
183 con = _getConnection();
184
185 ps = con.prepareStatement(
186 "INSERT INTO Map (key_, value_) values (?, ?)");
187
188 ps.setBytes(1, SerializableUtil.serialize(key));
189 ps.setBytes(2, SerializableUtil.serialize(value));
190
191 ps.execute();
192 }
193 catch (Exception e) {
194 throw new RuntimeException(e);
195 }
196 finally {
197 DataAccess.cleanUp(con, ps);
198 }
199 }
200
201 return value;
202 }
203
204 @Override
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 @Override
275 protected void finalize() throws Throwable {
276 try {
277 _deleteDatabase();
278 }
279 finally {
280 super.finalize();
281 }
282 }
283
284 private void _createDatabase() {
285 Connection con = null;
286
287 try {
288 con = _getConnection();
289
290 DB db = DBFactoryUtil.getDB(DB.TYPE_HYPERSONIC);
291
292 db.runSQL(con, _CREATE_SQL);
293 }
294 catch (Exception e) {
295 throw new RuntimeException(e);
296 }
297 finally {
298 DataAccess.cleanUp(con);
299 }
300 }
301
302 private void _deleteDatabase() throws Throwable {
303 File[] files = new File[] {
304 new File(_fileName + ".properties"),
305 new File(_fileName + ".script"), new File(_fileName + ".log"),
306 new File(_fileName + ".data"), new File(_fileName + ".backup")
307 };
308
309 for (File file : files) {
310 if (file.exists()) {
311 file.delete();
312 }
313 }
314 }
315
316 private Connection _getConnection() throws Exception {
317 return DriverManager.getConnection(
318 "jdbc:hsqldb:file:" + _fileName, "sa", "");
319 }
320
321 private int _getCount(K key, V value) {
322 Connection con = null;
323 PreparedStatement ps = null;
324 ResultSet rs = null;
325
326 try {
327 con = _getConnection();
328
329 String sql = "SELECT count(*) FROM Map ";
330
331 if ((key != null) && (value != null)) {
332 sql += "WHERE key_ = ? AND value_ = ?";
333
334 ps = con.prepareStatement(sql);
335
336 ps.setBytes(1, SerializableUtil.serialize(key));
337 ps.setBytes(2, SerializableUtil.serialize(value));
338 }
339 else if (key != null) {
340 sql += "WHERE key_ = ?";
341
342 ps = con.prepareStatement(sql);
343
344 ps.setBytes(1, SerializableUtil.serialize(key));
345 }
346 else if (value != null) {
347 sql += "WHERE value_ = ?";
348
349 ps = con.prepareStatement(sql);
350
351 ps.setBytes(1, SerializableUtil.serialize(value));
352 }
353 else {
354 ps = con.prepareStatement(sql);
355 }
356
357 rs = ps.executeQuery();
358
359 rs.next();
360
361 return rs.getInt(1);
362 }
363 catch (Exception e) {
364 throw new RuntimeException(e);
365 }
366 finally {
367 DataAccess.cleanUp(con, ps, rs);
368 }
369 }
370
371 private static final String _CREATE_SQL =
372 "CREATE TABLE Map (key_ BLOB not null, value_ BLOB not null)";
373
374 private static final String _KEY = "key_";
375
376 private static final String _VALUE = "value_";
377
378 private String _fileName;
379
380 }