1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
/*
* Copyright (c) 2006 Israfil Consulting Services Corporation
* Copyright (c) 2006 Christian Edward Gruber
* All Rights Reserved
*
* This software is licensed under the Berkeley Standard Distribution license,
* (BSD license), as defined below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Israfil Consulting Services nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* $Id: IterableResultSet.java 26 2006-02-13 16:35:44Z cgruber $
*/
package net.israfil.foundation.collections;
import java.lang.ref.WeakReference;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A simple wrapper that provides an Iterable implementation back-ended
* by a result-set. Allows a ResultSet to be used in a JDK 5.0 extended
* for-loop syntax.
*
* No result set can have more than one Iterable wrapper around it at a time.
* However, it is impossible for this object to know implicitly when it is
* no longer required (to free the reference). Therefore, when this
* wrapper is concluded, it should be disposed of via the dispose() method.
*
* @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
*/
public class IterableResultSet implements Iterable<Map<String,Object>> {
protected static final Map<ResultSet,IterableResultSet> iterables = new WeakHashMap<ResultSet,IterableResultSet>();
protected final WeakReference<ResultSet> resultRef;
public IterableResultSet(ResultSet result) {
if (iterables.containsKey(result)) throw new RuntimeException("Cannot have two IterableResultSet wrappers around the same resultset.");
this.resultRef = new WeakReference<ResultSet>(result);
}
public Iterator<Map<String,Object>> iterator() {
if (resultRef.get() == null) throw new RuntimeException("ResultSet object not available to iterate.");
return new ResultSetIterator(resultRef.get());
}
public void dispose() {
ResultSet rs = resultRef.get();
if (rs == null) return;
if (iterables.containsKey(rs)) {
iterables.get(rs).dispose();
}
resultRef.clear();
}
public static class ResultSetIterator implements Iterator<Map<String,Object>> {
private static final Logger logger = Logger.getLogger(ResultSetIterator.class.getName());
protected ResultSet result;
boolean hasNext = true;
public ResultSetIterator(ResultSet result) {
this.result = result;
try {
hasNext = result.first();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public boolean hasNext() {
return hasNext;
}
public Map<String,Object> next() {
try {
Map<String,Object> row = new HashMap<String,Object>();
for(int i = 1; i <= result.getMetaData().getColumnCount(); i++) {
row.put(result.getMetaData().getColumnName(i),result.getObject(i));
}
hasNext = result.next();
return row;
} catch (SQLException e) {
logger.log(Level.FINER,"SQLException thrown while iterating across result set.",e);
return null;
}
}
public void remove() {
throw new UnsupportedOperationException("Removal of records from underlying result set not supported.");
}
public void dispose() {
if (iterables.containsKey(result)) iterables.remove(result);
result = null;
}
public void finalize() throws Throwable {
dispose();
super.finalize();
}
}
}
|