001: /*
002: * ============================================================================
003: * GNU Lesser General Public License
004: * ============================================================================
005: *
006: * JasperReports - Free Java report-generating library.
007: * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
022: *
023: * JasperSoft Corporation
024: * 303 Second Street, Suite 450 North
025: * San Francisco, CA 94107
026: * http://www.jaspersoft.com
027: */
028:
029: /*
030: * Contributors:
031: * S. Brett Sutton - bsutton@idatam.com.au
032: */
033: package net.sf.jasperreports.engine;
034:
035: import java.awt.Image;
036: import java.io.BufferedReader;
037: import java.io.ByteArrayInputStream;
038: import java.io.ByteArrayOutputStream;
039: import java.io.CharArrayReader;
040: import java.io.CharArrayWriter;
041: import java.io.IOException;
042: import java.io.InputStream;
043: import java.io.Reader;
044: import java.sql.Blob;
045: import java.sql.Clob;
046: import java.sql.ResultSet;
047: import java.sql.ResultSetMetaData;
048: import java.sql.SQLException;
049: import java.sql.Types;
050: import java.util.HashMap;
051: import java.util.Map;
052:
053: import net.sf.jasperreports.engine.util.JRImageLoader;
054:
055: /**
056: * An implementation of a data source that uses a supplied <tt>ResultSet</tt>.
057: * @author Teodor Danciu (teodord@users.sourceforge.net)
058: * @version $Id: JRResultSetDataSource.java 1418 2006-10-05 14:05:26Z lucianc $
059: */
060: public class JRResultSetDataSource implements JRDataSource {
061:
062: private static final String INDEXED_COLUMN_PREFIX = "COLUMN_";
063: private static final int INDEXED_COLUMN_PREFIX_LENGTH = INDEXED_COLUMN_PREFIX
064: .length();
065:
066: /**
067: *
068: */
069: private ResultSet resultSet = null;
070: private Map columnIndexMap = new HashMap();
071:
072: /**
073: *
074: */
075: public JRResultSetDataSource(ResultSet rs) {
076: resultSet = rs;
077: }
078:
079: /**
080: *
081: */
082: public boolean next() throws JRException {
083: boolean hasNext = false;
084:
085: if (resultSet != null) {
086: try {
087: hasNext = resultSet.next();
088: } catch (SQLException e) {
089: throw new JRException("Unable to get next record.", e);
090: }
091: }
092:
093: return hasNext;
094: }
095:
096: /**
097: *
098: */
099: public Object getFieldValue(JRField field) throws JRException {
100: Object objValue = null;
101:
102: if (field != null && resultSet != null) {
103: Integer columnIndex = getColumnIndex(field.getName());
104: Class clazz = field.getValueClass();
105:
106: try {
107: if (clazz.equals(java.lang.Boolean.class)) {
108: objValue = resultSet.getBoolean(columnIndex
109: .intValue()) ? Boolean.TRUE : Boolean.FALSE;
110: } else if (clazz.equals(java.lang.Byte.class)) {
111: objValue = new Byte(resultSet.getByte(columnIndex
112: .intValue()));
113: if (resultSet.wasNull()) {
114: objValue = null;
115: }
116: } else if (clazz.equals(java.util.Date.class)) {
117: objValue = resultSet
118: .getDate(columnIndex.intValue());
119: if (resultSet.wasNull()) {
120: objValue = null;
121: }
122: } else if (clazz.equals(java.sql.Timestamp.class)) {
123: objValue = resultSet.getTimestamp(columnIndex
124: .intValue());
125: if (resultSet.wasNull()) {
126: objValue = null;
127: }
128: } else if (clazz.equals(java.sql.Time.class)) {
129: objValue = resultSet
130: .getTime(columnIndex.intValue());
131: if (resultSet.wasNull()) {
132: objValue = null;
133: }
134: } else if (clazz.equals(java.lang.Double.class)) {
135: objValue = new Double(resultSet
136: .getDouble(columnIndex.intValue()));
137: if (resultSet.wasNull()) {
138: objValue = null;
139: }
140: } else if (clazz.equals(java.lang.Float.class)) {
141: objValue = new Float(resultSet.getFloat(columnIndex
142: .intValue()));
143: if (resultSet.wasNull()) {
144: objValue = null;
145: }
146: } else if (clazz.equals(java.lang.Integer.class)) {
147: objValue = new Integer(resultSet.getInt(columnIndex
148: .intValue()));
149: if (resultSet.wasNull()) {
150: objValue = null;
151: }
152: } else if (clazz.equals(java.io.InputStream.class)) {
153: byte[] bytes = readBytes(columnIndex);
154:
155: if (bytes == null) {
156: objValue = null;
157: } else {
158: objValue = new ByteArrayInputStream(bytes);
159: }
160: } else if (clazz.equals(java.lang.Long.class)) {
161: objValue = new Long(resultSet.getLong(columnIndex
162: .intValue()));
163: if (resultSet.wasNull()) {
164: objValue = null;
165: }
166: } else if (clazz.equals(java.lang.Short.class)) {
167: objValue = new Short(resultSet.getShort(columnIndex
168: .intValue()));
169: if (resultSet.wasNull()) {
170: objValue = null;
171: }
172: } else if (clazz.equals(java.math.BigDecimal.class)) {
173: objValue = resultSet.getBigDecimal(columnIndex
174: .intValue());
175: if (resultSet.wasNull()) {
176: objValue = null;
177: }
178: } else if (clazz.equals(java.lang.String.class)) {
179: int columnType = resultSet.getMetaData()
180: .getColumnType(columnIndex.intValue());
181: switch (columnType) {
182: case Types.CLOB:
183: Clob clob = resultSet.getClob(columnIndex
184: .intValue());
185: if (resultSet.wasNull()) {
186: objValue = null;
187: } else {
188: objValue = clobToString(clob);
189: }
190: break;
191:
192: default:
193: objValue = resultSet.getString(columnIndex
194: .intValue());
195: if (resultSet.wasNull()) {
196: objValue = null;
197: }
198: break;
199: }
200: } else if (clazz.equals(Clob.class)) {
201: objValue = resultSet
202: .getClob(columnIndex.intValue());
203: if (resultSet.wasNull()) {
204: objValue = null;
205: }
206: } else if (clazz.equals(Reader.class)) {
207: Reader reader = null;
208: long size = -1;
209:
210: int columnType = resultSet.getMetaData()
211: .getColumnType(columnIndex.intValue());
212: switch (columnType) {
213: case Types.CLOB:
214: Clob clob = resultSet.getClob(columnIndex
215: .intValue());
216: if (!resultSet.wasNull()) {
217: reader = clob.getCharacterStream();
218: size = clob.length();
219: }
220: break;
221:
222: default:
223: reader = resultSet
224: .getCharacterStream(columnIndex
225: .intValue());
226: if (resultSet.wasNull()) {
227: reader = null;
228: }
229: }
230:
231: if (reader == null) {
232: objValue = null;
233: } else {
234: objValue = getArrayReader(reader, size);
235: }
236: } else if (clazz.equals(Blob.class)) {
237: objValue = resultSet
238: .getBlob(columnIndex.intValue());
239: if (resultSet.wasNull()) {
240: objValue = null;
241: }
242: } else if (clazz.equals(Image.class)) {
243: byte[] bytes = readBytes(columnIndex);
244:
245: if (bytes == null) {
246: objValue = null;
247: } else {
248: objValue = JRImageLoader.loadImage(bytes);
249: }
250: } else {
251: objValue = resultSet.getObject(columnIndex
252: .intValue());
253: }
254: } catch (Exception e) {
255: throw new JRException("Unable to get value for field '"
256: + field.getName() + "' of class '"
257: + clazz.getName() + "'", e);
258: }
259: }
260:
261: return objValue;
262: }
263:
264: /**
265: *
266: */
267: private Integer getColumnIndex(String fieldName) throws JRException {
268: Integer columnIndex = (Integer) columnIndexMap.get(fieldName);
269: if (columnIndex == null) {
270: try {
271: columnIndex = searchColumnByName(fieldName);
272:
273: if (columnIndex == null) {
274: columnIndex = searchColumnByLabel(fieldName);
275: }
276:
277: if (columnIndex == null
278: && fieldName.startsWith(INDEXED_COLUMN_PREFIX)) {
279: columnIndex = new Integer(fieldName
280: .substring(INDEXED_COLUMN_PREFIX_LENGTH));
281: if (columnIndex.intValue() <= 0
282: || columnIndex.intValue() > resultSet
283: .getMetaData().getColumnCount()) {
284: throw new JRException(
285: "Column index out of range : "
286: + columnIndex);
287: }
288: }
289:
290: if (columnIndex == null) {
291: throw new JRException("Unknown column name : "
292: + fieldName);
293: }
294: } catch (SQLException e) {
295: throw new JRException(
296: "Unable to retrieve result set metadata.", e);
297: }
298:
299: columnIndexMap.put(fieldName, columnIndex);
300: }
301:
302: return columnIndex;
303: }
304:
305: protected Integer searchColumnByName(String fieldName)
306: throws SQLException {
307: Integer columnIndex = null;
308: ResultSetMetaData metadata = resultSet.getMetaData();
309: for (int i = 1; i <= metadata.getColumnCount(); i++) {
310: String columnName = metadata.getColumnName(i);
311: if (fieldName.equalsIgnoreCase(columnName)) {
312: columnIndex = new Integer(i);
313: break;
314: }
315: }
316: return columnIndex;
317: }
318:
319: protected Integer searchColumnByLabel(String fieldName)
320: throws SQLException {
321: Integer columnIndex = null;
322: ResultSetMetaData metadata = resultSet.getMetaData();
323: for (int i = 1; i <= metadata.getColumnCount(); i++) {
324: String columnLabel = metadata.getColumnLabel(i);
325: if (columnLabel != null
326: && fieldName.equalsIgnoreCase(columnLabel)) {
327: columnIndex = new Integer(i);
328: break;
329: }
330: }
331: return columnIndex;
332: }
333:
334: protected String clobToString(Clob clob) throws JRException {
335: try {
336: int bufSize = 8192;
337: char[] buf = new char[bufSize];
338:
339: Reader reader = new BufferedReader(clob
340: .getCharacterStream(), bufSize);
341: StringBuffer str = new StringBuffer((int) clob.length());
342:
343: for (int read = reader.read(buf); read > 0; read = reader
344: .read(buf)) {
345: str.append(buf, 0, read);
346: }
347:
348: return str.toString();
349: } catch (SQLException e) {
350: throw new JRException("Unable to read clob value", e);
351: } catch (IOException e) {
352: throw new JRException("Unable to read clob value", e);
353: }
354: }
355:
356: protected CharArrayReader getArrayReader(Reader reader, long size)
357: throws IOException {
358: char[] buf = new char[8192];
359: CharArrayWriter bufWriter = new CharArrayWriter(
360: (size > 0) ? (int) size : 8192);
361:
362: BufferedReader bufReader = new BufferedReader(reader, 8192);
363: for (int read = bufReader.read(buf); read > 0; read = bufReader
364: .read(buf)) {
365: bufWriter.write(buf, 0, read);
366: }
367: bufWriter.flush();
368:
369: return new CharArrayReader(bufWriter.toCharArray());
370: }
371:
372: protected byte[] readBytes(Integer columnIndex)
373: throws SQLException, IOException {
374: InputStream is = null;
375: long size = -1;
376:
377: int columnType = resultSet.getMetaData().getColumnType(
378: columnIndex.intValue());
379: switch (columnType) {
380: case Types.BLOB:
381: Blob blob = resultSet.getBlob(columnIndex.intValue());
382: if (!resultSet.wasNull()) {
383: is = blob.getBinaryStream();
384: size = blob.length();
385: }
386: break;
387:
388: default:
389: is = resultSet.getBinaryStream(columnIndex.intValue());
390: if (resultSet.wasNull()) {
391: is = null;
392: }
393: }
394:
395: byte[] bytes = null;
396: if (is != null) {
397: bytes = readBytes(is, size);
398: }
399:
400: return bytes;
401: }
402:
403: protected byte[] readBytes(InputStream is, long size)
404: throws IOException {
405: ByteArrayOutputStream baos = new ByteArrayOutputStream(
406: size > 0 ? (int) size : 1000);
407: byte[] bytes = new byte[1000];
408: int ln = 0;
409: try {
410: while ((ln = is.read(bytes)) > 0) {
411: baos.write(bytes, 0, ln);
412: }
413: baos.flush();
414: } finally {
415: try {
416: baos.close();
417: } catch (IOException e) {
418: }
419: }
420: return baos.toByteArray();
421: }
422: }
|