All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.jasperreports.engine.JRResultSetDataSource Maven / Gradle / Ivy

There is a newer version: 6.21.2
Show newest version
/*
 * JasperReports - Free Java Reporting Library.
 * Copyright (C) 2001 - 2014 TIBCO Software Inc. All rights reserved.
 * http://www.jaspersoft.com
 *
 * Unless you have purchased a commercial license agreement from Jaspersoft,
 * the following license terms apply:
 *
 * This program is part of JasperReports.
 *
 * JasperReports is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JasperReports is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with JasperReports. If not, see .
 */

/*
 * Contributors:
 * S. Brett Sutton - [email protected]
 */
package net.sf.jasperreports.engine;

import java.awt.Image;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import net.sf.jasperreports.engine.query.JRJdbcQueryExecuterFactory;
import net.sf.jasperreports.engine.util.JRImageLoader;


/**
 * This is a default implementation of the
 * {@link net.sf.jasperreports.engine.JRDataSource} interface. Since most reports are
 * generated using data from a relational database, JasperReports includes by default this
 * implementation that wraps a java.sql.ResultSet object.
 * 

* This class can be instantiated intentionally to wrap already loaded result sets before * passing them to the report-filling routines, but it is also used by the reporting engine to * wrap the data retrieved from the database after having executed the report query (if * present) through JDBC. * @author Teodor Danciu ([email protected]) */ public class JRResultSetDataSource implements JRDataSource { private static final Log log = LogFactory.getLog(JRResultSetDataSource.class); public static final String INDEXED_COLUMN_PREFIX = "COLUMN_"; private static final int INDEXED_COLUMN_PREFIX_LENGTH = INDEXED_COLUMN_PREFIX.length(); public static final String EXCEPTION_MESSAGE_KEY_RESULT_SET_CLOB_VALUE_READ_FAILURE = "data.result.set.clob.value.read.failure"; public static final String EXCEPTION_MESSAGE_KEY_RESULT_SET_COLUMN_INDEX_OUT_OF_RANGE = "data.result.set.column.index.out.of.range"; public static final String EXCEPTION_MESSAGE_KEY_RESULT_SET_FIELD_VALUE_NOT_RETRIEVED = "data.result.set.field.value.not.retrieved"; public static final String EXCEPTION_MESSAGE_KEY_RESULT_SET_METADATA_NOT_RETRIEVED = "data.result.set.metadata.not.retrieved"; public static final String EXCEPTION_MESSAGE_KEY_RESULT_SET_UNKNOWN_COLUMN_NAME = "data.result.set.unknown.column.name"; public static final String EXCEPTION_MESSAGE_KEY_RESULT_SET_NEXT_RECORD_NOT_RETRIEVED = "data.result.set.next.record.not.retrieved"; /** * */ private JasperReportsContext jasperReportsContext; private ResultSet resultSet; private Map columnIndexMap = new HashMap(); private TimeZone timeZone; private boolean timeZoneOverride; private TimeZone reportTimeZone; private Map fieldCalendars = new HashMap(); /** * */ public JRResultSetDataSource(JasperReportsContext jasperReportsContext, ResultSet resultSet) { this.jasperReportsContext = jasperReportsContext; this.resultSet = resultSet; } /** * @see #JRResultSetDataSource(JasperReportsContext, ResultSet) */ public JRResultSetDataSource(ResultSet resultSet) { this(DefaultJasperReportsContext.getInstance(), resultSet); } @Override public boolean next() throws JRException { boolean hasNext = false; if (resultSet != null) { try { hasNext = resultSet.next(); } catch (SQLException e) { throw new JRException( EXCEPTION_MESSAGE_KEY_RESULT_SET_NEXT_RECORD_NOT_RETRIEVED, null, e); } } return hasNext; } @Override public Object getFieldValue(JRField field) throws JRException { Object objValue = null; if (field != null && resultSet != null) { Integer columnIndex = getColumnIndex(field.getName()); Class clazz = field.getValueClass(); try { if (clazz.equals(java.lang.Boolean.class)) { objValue = resultSet.getBoolean(columnIndex.intValue()) ? Boolean.TRUE : Boolean.FALSE; if(resultSet.wasNull()) { objValue = null; } } else if (clazz.equals(java.lang.Byte.class)) { objValue = new Byte(resultSet.getByte(columnIndex.intValue())); if(resultSet.wasNull()) { objValue = null; } } else if ( clazz.equals(java.util.Date.class) || clazz.equals(java.sql.Date.class) ) { objValue = readDate(columnIndex, field); } else if (clazz.equals(java.sql.Timestamp.class)) { objValue = readTimestamp(columnIndex, field); } else if (clazz.equals(java.sql.Time.class)) { objValue = readTime(columnIndex, field); } else if (clazz.equals(java.lang.Double.class)) { objValue = new Double(resultSet.getDouble(columnIndex.intValue())); if(resultSet.wasNull()) { objValue = null; } } else if (clazz.equals(java.lang.Float.class)) { objValue = new Float(resultSet.getFloat(columnIndex.intValue())); if(resultSet.wasNull()) { objValue = null; } } else if (clazz.equals(java.lang.Integer.class)) { objValue = Integer.valueOf(resultSet.getInt(columnIndex.intValue())); if(resultSet.wasNull()) { objValue = null; } } else if (clazz.equals(java.io.InputStream.class)) { byte[] bytes = readBytes(columnIndex); if(bytes == null) { objValue = null; } else { objValue = new ByteArrayInputStream(bytes); } } else if (clazz.equals(java.lang.Long.class)) { objValue = new Long(resultSet.getLong(columnIndex.intValue())); if(resultSet.wasNull()) { objValue = null; } } else if (clazz.equals(java.lang.Short.class)) { objValue = new Short(resultSet.getShort(columnIndex.intValue())); if(resultSet.wasNull()) { objValue = null; } } else if (clazz.equals(java.math.BigDecimal.class)) { objValue = resultSet.getBigDecimal(columnIndex.intValue()); if(resultSet.wasNull()) { objValue = null; } } else if (clazz.equals(java.lang.String.class)) { int columnType = resultSet.getMetaData().getColumnType(columnIndex.intValue()); switch (columnType) { case Types.CLOB: Clob clob = resultSet.getClob(columnIndex.intValue()); if (resultSet.wasNull()) { objValue = null; } else { objValue = clobToString(clob); } break; default: objValue = resultSet.getString(columnIndex.intValue()); if(resultSet.wasNull()) { objValue = null; } break; } } else if (clazz.equals(Clob.class)) { objValue = resultSet.getClob(columnIndex.intValue()); if(resultSet.wasNull()) { objValue = null; } } else if (clazz.equals(Reader.class)) { Reader reader = null; long size = -1; int columnType = resultSet.getMetaData().getColumnType(columnIndex.intValue()); switch (columnType) { case Types.CLOB: Clob clob = resultSet.getClob(columnIndex.intValue()); if (!resultSet.wasNull()) { reader = clob.getCharacterStream(); size = clob.length(); } break; default: reader = resultSet.getCharacterStream(columnIndex.intValue()); if (resultSet.wasNull()) { reader = null; } } if (reader == null) { objValue = null; } else { objValue = getArrayReader(reader, size); } } else if (clazz.equals(Blob.class)) { objValue = resultSet.getBlob(columnIndex.intValue()); if(resultSet.wasNull()) { objValue = null; } } else if (clazz.equals(Image.class)) { byte[] bytes = readBytes(columnIndex); if(bytes == null) { objValue = null; } else { objValue = JRImageLoader.getInstance(jasperReportsContext).loadAwtImageFromBytes(bytes); } } else { objValue = resultSet.getObject(columnIndex.intValue()); } } catch (Exception e) { throw new JRException( EXCEPTION_MESSAGE_KEY_RESULT_SET_FIELD_VALUE_NOT_RETRIEVED, new Object[]{field.getName(), clazz.getName()}, e); } } return objValue; } protected Object readDate(Integer columnIndex, JRField field) throws SQLException { Calendar calendar = getFieldCalendar(field); java.sql.Date objValue = calendar == null ? resultSet.getDate(columnIndex.intValue()) : resultSet.getDate(columnIndex.intValue(), calendar); if(resultSet.wasNull()) { objValue = null; } if (log.isDebugEnabled()) { log.debug("date field " + field.getName() + " is " + (objValue == null ? "null" : (objValue + " (" + objValue.getTime() + ")"))); } return objValue; } protected Object readTimestamp(Integer columnIndex, JRField field) throws SQLException { Calendar calendar = getFieldCalendar(field); java.sql.Timestamp objValue = calendar == null ? resultSet.getTimestamp(columnIndex.intValue()) : resultSet.getTimestamp(columnIndex.intValue(), calendar); if(resultSet.wasNull()) { objValue = null; } if (log.isDebugEnabled()) { log.debug("timestamp field " + field.getName() + " is " + (objValue == null ? "null" : (objValue + " (" + objValue.getTime() + ")"))); } return objValue; } protected Object readTime(Integer columnIndex, JRField field) throws SQLException { Calendar calendar = getFieldCalendar(field); java.sql.Time objValue = calendar == null ? resultSet.getTime(columnIndex.intValue()) : resultSet.getTime(columnIndex.intValue(), calendar); if(resultSet.wasNull()) { objValue = null; } if (log.isDebugEnabled()) { log.debug("time field " + field.getName() + " is " + (objValue == null ? "null" : (objValue + " (" + objValue.getTime() + ")"))); } return objValue; } /** * */ private Integer getColumnIndex(String fieldName) throws JRException { Integer columnIndex = columnIndexMap.get(fieldName); if (columnIndex == null) { try { columnIndex = searchColumnByName(fieldName); if (columnIndex == null) { columnIndex = searchColumnByLabel(fieldName); } if (columnIndex == null && fieldName.startsWith(INDEXED_COLUMN_PREFIX)) { columnIndex = Integer.valueOf(fieldName.substring(INDEXED_COLUMN_PREFIX_LENGTH)); if ( columnIndex.intValue() <= 0 || columnIndex.intValue() > resultSet.getMetaData().getColumnCount() ) { throw new JRException( EXCEPTION_MESSAGE_KEY_RESULT_SET_COLUMN_INDEX_OUT_OF_RANGE, new Object[]{columnIndex}); } } if (columnIndex == null) { throw new JRException( EXCEPTION_MESSAGE_KEY_RESULT_SET_UNKNOWN_COLUMN_NAME, new Object[]{fieldName}); } } catch (SQLException e) { throw new JRException( EXCEPTION_MESSAGE_KEY_RESULT_SET_METADATA_NOT_RETRIEVED, null, e); } if (log.isDebugEnabled()) { try { ResultSetMetaData metaData = resultSet.getMetaData(); log.debug("field " + fieldName + " has type " + metaData.getColumnType(columnIndex) + "/" + metaData.getColumnTypeName(columnIndex) + ", class " + metaData.getColumnClassName(columnIndex)); } catch (SQLException e) { log.debug("failed to read result set metadata", e); } } columnIndexMap.put(fieldName, columnIndex); } return columnIndex; } protected Integer searchColumnByName(String fieldName) throws SQLException { Integer columnIndex = null; ResultSetMetaData metadata = resultSet.getMetaData(); for(int i = 1; i <= metadata.getColumnCount(); i++) { String columnName = metadata.getColumnName(i); if (fieldName.equalsIgnoreCase(columnName)) { columnIndex = Integer.valueOf(i); break; } } return columnIndex; } protected Integer searchColumnByLabel(String fieldName) throws SQLException { Integer columnIndex = null; ResultSetMetaData metadata = resultSet.getMetaData(); for(int i = 1; i <= metadata.getColumnCount(); i++) { String columnLabel = metadata.getColumnLabel(i); if (columnLabel != null && fieldName.equalsIgnoreCase(columnLabel)) { columnIndex = Integer.valueOf(i); break; } } return columnIndex; } protected String clobToString(Clob clob) throws JRException { try { int bufSize = 8192; char[] buf = new char[bufSize]; Reader reader = new BufferedReader(clob.getCharacterStream(), bufSize); StringBuilder str = new StringBuilder((int) clob.length()); for (int read = reader.read(buf); read > 0; read = reader.read(buf)) { str.append(buf, 0, read); } return str.toString(); } catch (SQLException e) { throw new JRException( EXCEPTION_MESSAGE_KEY_RESULT_SET_CLOB_VALUE_READ_FAILURE, null, e); } catch (IOException e) { throw new JRException( EXCEPTION_MESSAGE_KEY_RESULT_SET_CLOB_VALUE_READ_FAILURE, null, e); } } protected CharArrayReader getArrayReader(Reader reader, long size) throws IOException { char[] buf = new char[8192]; CharArrayWriter bufWriter = new CharArrayWriter((size > 0) ? (int) size : 8192); BufferedReader bufReader = new BufferedReader(reader, 8192); for (int read = bufReader.read(buf); read > 0; read = bufReader.read(buf)) { bufWriter.write(buf, 0, read); } bufWriter.flush(); return new CharArrayReader(bufWriter.toCharArray()); } protected byte[] readBytes(Integer columnIndex) throws SQLException, IOException { InputStream is = null; long size = -1; int columnType = resultSet.getMetaData().getColumnType(columnIndex.intValue()); switch (columnType) { case Types.BLOB: Blob blob = resultSet.getBlob(columnIndex.intValue()); if (!resultSet.wasNull()) { is = blob.getBinaryStream(); size = blob.length(); } break; default: is = resultSet.getBinaryStream(columnIndex.intValue()); if (resultSet.wasNull()) { is = null; } } byte[] bytes = null; if (is != null) { bytes = readBytes(is, size); } return bytes; } protected byte[] readBytes(InputStream is, long size) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(size > 0 ? (int) size : 1000); byte[] bytes = new byte[1000]; int ln = 0; try { while ((ln = is.read(bytes)) > 0) { baos.write(bytes, 0, ln); } baos.flush(); } finally { try { baos.close(); } catch(IOException e) { } } return baos.toByteArray(); } /** * Sets the default time zone to be used for retrieving date/time values from the * result set. * * In most cases no explicit time zone conversion would be required for retrieving * date/time values from the DB, and this parameter should be null. * * @param timeZone the default time zone * @param override whether the default time zone overrides time zones specified * as field-level properties * @see JRJdbcQueryExecuterFactory#PROPERTY_TIME_ZONE */ public void setTimeZone(TimeZone timeZone, boolean override) { this.timeZone = timeZone; this.timeZoneOverride = override; } /** * Sets the report time zone, which is the one used to display datetime values in the report. * * The time zone is used when the {@link JRJdbcQueryExecuterFactory#PROPERTY_TIME_ZONE} property * is set to REPORT_TIME_ZONE. * * @param reportTimeZone the time zone used to display datetime values in the report */ public void setReportTimeZone(TimeZone reportTimeZone) { this.reportTimeZone = reportTimeZone; } protected Calendar getFieldCalendar(JRField field) { if (fieldCalendars.containsKey(field)) { return fieldCalendars.get(field); } Calendar calendar = createFieldCalendar(field); fieldCalendars.put(field, calendar); if (log.isDebugEnabled()) { log.debug("calendar for field " + field.getName() + " is " + calendar); } return calendar; } protected Calendar createFieldCalendar(JRField field) { TimeZone tz; if (timeZoneOverride) { // if we have a parameter, use it tz = timeZone; } else { if (field.hasProperties() && field.getPropertiesMap().containsProperty( JRJdbcQueryExecuterFactory.PROPERTY_TIME_ZONE)) { // read the field level property String timezoneId = JRPropertiesUtil.getInstance(jasperReportsContext).getProperty(field, JRJdbcQueryExecuterFactory.PROPERTY_TIME_ZONE); tz = resolveTimeZone(timezoneId); } else { // dataset/default property tz = timeZone; } } // using default JVM locale for the calendar Calendar cal = tz == null ? null : Calendar.getInstance(tz); return cal; } protected TimeZone resolveTimeZone(String timezoneId) { TimeZone tz; if (timezoneId == null || timezoneId.length() == 0) { tz = null; } else if (timezoneId.equals(JRParameter.REPORT_TIME_ZONE)) { // using the report timezone tz = reportTimeZone; } else { // resolving as tz ID tz = TimeZone.getTimeZone(timezoneId); } return tz; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy