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.portal.kernel.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 public Set<V> getAll(Object key) {
088 Connection con = null;
089 PreparedStatement ps = null;
090 ResultSet rs = null;
091
092 Set<V> values = null;
093
094 try {
095 con = _getConnection();
096
097 ps = con.prepareStatement("SELECT value_ FROM Map WHERE key_ = ?");
098
099 ps.setBytes(1, SerializableUtil.serialize(key));
100
101 rs = ps.executeQuery();
102
103 while (rs.next()) {
104 if (values == null) {
105 values = new HashSet<V>();
106 }
107
108 V value = null;
109
110 value = (V)SerializableUtil.deserialize(rs.getBytes(_VALUE));
111
112 values.add(value);
113 }
114 }
115 catch (Exception e) {
116 throw new RuntimeException(e);
117 }
118 finally {
119 DataAccess.cleanUp(con, ps, rs);
120 }
121
122 return values;
123 }
124
125 public boolean isEmpty() {
126 int count = _getCount(null, null);
127
128 if (count == 0) {
129 return true;
130 }
131 else {
132 return false;
133 }
134 }
135
136 public Set<K> keySet() {
137 Connection con = null;
138 PreparedStatement ps = null;
139 ResultSet rs = null;
140
141 Set<K> keys = null;
142
143 try {
144 con = _getConnection();
145
146 ps = con.prepareStatement("SELECT DISTINCT (key_) FROM Map ");
147
148 rs = ps.executeQuery();
149
150 while (rs.next()) {
151 if (keys == null) {
152 keys = new HashSet<K>();
153 }
154
155 K key = null;
156
157 key = (K)SerializableUtil.deserialize(rs.getBytes(_KEY));
158
159 keys.add(key);
160 }
161 }
162 catch (Exception e) {
163 throw new RuntimeException(e);
164 }
165 finally {
166 DataAccess.cleanUp(con, ps, rs);
167 }
168
169 return keys;
170 }
171
172 public V put(K key, V value) {
173 if ((key == null) || (value == null)) {
174 return null;
175 }
176
177 if (_getCount(key, value) == 0) {
178 Connection con = null;
179 PreparedStatement ps = null;
180
181 try {
182 con = _getConnection();
183
184 ps = con.prepareStatement(
185 "INSERT INTO Map (key_, value_) values (?, ?)");
186
187 ps.setBytes(1, SerializableUtil.serialize(key));
188 ps.setBytes(2, SerializableUtil.serialize(value));
189
190 ps.execute();
191 }
192 catch (Exception e) {
193 throw new RuntimeException(e);
194 }
195 finally {
196 DataAccess.cleanUp(con, ps);
197 }
198 }
199
200 return value;
201 }
202
203 public Set<V> putAll(K key, Collection<? extends V> values) {
204 Set<V> curValues = getAll(key);
205
206 if ((values == null) || values.isEmpty()) {
207 return curValues;
208 }
209
210 if (curValues == null) {
211 values = new HashSet<V>();
212 }
213
214 for (V value: values) {
215 if (!curValues.contains(value)) {
216 curValues.add(value);
217
218 put(key, value);
219 }
220 }
221
222 return curValues;
223 }
224
225 public V remove(Object key) {
226 Connection con = null;
227 PreparedStatement ps = null;
228 ResultSet rs = null;
229
230 V firstValue = null;
231
232 try {
233 con = _getConnection();
234
235 ps = con.prepareStatement("SELECT value_ FROM Map WHERE key_ = ?");
236
237 ps.setBytes(1, SerializableUtil.serialize(key));
238
239 rs = ps.executeQuery();
240
241 if (rs.next()) {
242 firstValue = (V)SerializableUtil.deserialize(
243 rs.getBytes(_VALUE));
244 }
245 }
246 catch (Exception e) {
247 throw new RuntimeException(e);
248 }
249 finally {
250 DataAccess.cleanUp(con, ps, rs);
251 }
252
253 try {
254 con = _getConnection();
255
256 ps = con.prepareStatement("DELETE FROM Map WHERE key_ = ?");
257
258 ps.setBytes(1, SerializableUtil.serialize(key));
259
260 ps.execute();
261 }
262 catch (Exception e) {
263 throw new RuntimeException(e);
264 }
265 finally {
266 DataAccess.cleanUp(con, ps);
267 }
268
269 return firstValue;
270 }
271
272 protected void finalize() throws Throwable {
273 try {
274 _deleteDatabase();
275 }
276 finally {
277 super.finalize();
278 }
279 }
280
281 private void _createDatabase() {
282 Connection con = null;
283
284 try {
285 con = _getConnection();
286
287 DB db = DBFactoryUtil.getDB(DB.TYPE_HYPERSONIC);
288
289 db.runSQL(con, _CREATE_SQL);
290 }
291 catch (Exception e) {
292 throw new RuntimeException(e);
293 }
294 finally {
295 DataAccess.cleanUp(con);
296 }
297 }
298
299 private void _deleteDatabase() throws Throwable {
300 File[] files = new File[] {
301 new File(_fileName + ".properties"),
302 new File(_fileName + ".script"),
303 new File(_fileName + ".log"),
304 new File(_fileName + ".data"),
305 new File(_fileName + ".backup")
306 };
307
308 for (File file : files) {
309 if (file.exists()) {
310 file.delete();
311 }
312 }
313 }
314
315 private Connection _getConnection() throws Exception {
316 return DriverManager.getConnection(
317 "jdbc:hsqldb:file:" + _fileName, "sa", "");
318 }
319
320 private int _getCount(K key, V value) {
321 Connection con = null;
322 PreparedStatement ps = null;
323 ResultSet rs = null;
324
325 try {
326 con = _getConnection();
327
328 String sql = "SELECT count(*) FROM Map ";
329
330 if ((key != null) && (value != null)) {
331 sql += "WHERE key_ = ? AND value_ = ?";
332
333 ps = con.prepareStatement(sql);
334
335 ps.setBytes(1, SerializableUtil.serialize(key));
336 ps.setBytes(2, SerializableUtil.serialize(value));
337 }
338 else if (key != null) {
339 sql += "WHERE key_ = ?";
340
341 ps = con.prepareStatement(sql);
342
343 ps.setBytes(1, SerializableUtil.serialize(key));
344 }
345 else if (value != null) {
346 sql += "WHERE value_ = ?";
347
348 ps = con.prepareStatement(sql);
349
350 ps.setBytes(1, SerializableUtil.serialize(value));
351 }
352 else {
353 ps = con.prepareStatement(sql);
354 }
355
356 rs = ps.executeQuery();
357
358 rs.next();
359
360 return rs.getInt(1);
361 }
362 catch (Exception e) {
363 throw new RuntimeException(e);
364 }
365 finally {
366 DataAccess.cleanUp(con, ps, rs);
367 }
368 }
369
370 private static final String _CREATE_SQL =
371 "CREATE TABLE Map (key_ BLOB not null, value_ BLOB not null, primary " +
372 "key (key_, value_))";
373
374 private static final String _KEY = "key_";
375
376 private static final String _VALUE = "value_";
377
378 private String _fileName;
379
380 }