/* * Copyright 2001-2008 Geert Bevin (gbevin[remove] at uwyn dot com) * Licensed under the Apache License, Version 2.0 (the "License") * $Id: Common.java 3918 2008-04-14 17:35:35Z gbevin $ */ package com.uwyn.rife.database.types.databasedrivers; import java.sql.*; import com.uwyn.rife.database.DbPreparedStatement; import com.uwyn.rife.database.exceptions.DatabaseException; import com.uwyn.rife.database.types.SqlConversion; import com.uwyn.rife.site.Constrained; import com.uwyn.rife.site.ConstrainedProperty; import com.uwyn.rife.tools.FileUtils; import com.uwyn.rife.tools.JavaSpecificationUtils; import com.uwyn.rife.tools.StringUtils; import java.io.InputStream; import java.io.StringReader; import java.math.BigDecimal; import java.util.Calendar; import java.util.Date; public abstract class Common implements SqlConversion { protected abstract Object retrieveFieldObject(ResultSet resultSet, int columnNumber, int type) throws SQLException; /* * UNSUPPORTED SQL TYPES : * DATALINK * DISTINCT * NULL * STRUCT */ public Object getTypedObject(ResultSet resultSet, int columnNumber, int type, Class targetType) throws DatabaseException { if (null == resultSet) throw new IllegalArgumentException("resultSet can't be null."); if (columnNumber < 1) throw new IllegalArgumentException("columnNumber must be equal or bigger than 1."); if (null == targetType) throw new IllegalArgumentException("targetType can't be null."); try { Object field = retrieveFieldObject(resultSet, columnNumber, type); if (null == field) { return null; } Object typed = getTypedObject(field, targetType); if (null == typed) { throw new DatabaseException("Impossible to return a compatible typed object. The target type is '" + targetType.getName() + "' and the result type is '" + field.getClass().getName() + "'."); } return typed; } catch (SQLException e) { throw new DatabaseException("Unexpected exception while obtaining a typed object for column '" + columnNumber + "', type '" + type + "' and target type '" + targetType.getName() + "'", e); } } protected Object getTypedObject(Object result, Class targetType) { try { if (!targetType.isInstance(result)) { Class result_class = result.getClass(); if (targetType == boolean.class && result_class == Boolean.class || targetType == byte.class && result_class == Byte.class || targetType == double.class && result_class == Double.class || targetType == float.class && result_class == Float.class || targetType == int.class && result_class == Integer.class || targetType == long.class && result_class == Long.class || targetType == short.class && result_class == Short.class || targetType == char.class && result_class == Character.class) { return result; } else { try { if (targetType == boolean.class || targetType == Boolean.class) { return Boolean.valueOf(StringUtils.convertToBoolean(result.toString())); } else if (targetType == byte.class || targetType == Byte.class) { return new Byte(result.toString()); } else if (targetType == double.class || targetType == Double.class) { return new Double(result.toString()); } else if (targetType == float.class || targetType == Float.class) { return new Float(result.toString()); } else if (targetType == int.class || targetType == Integer.class) { return new Integer(result.toString()); } else if (targetType == long.class || targetType == Long.class) { return new Long(result.toString()); } else if (targetType == short.class || targetType == Short.class) { return new Short(result.toString()); } else if (targetType == BigDecimal.class) { return new BigDecimal(result.toString()); } else if (targetType == char.class || targetType == Character.class) { return new Character(result.toString().charAt(0)); } else if (targetType == StringBuilder.class) { return new StringBuilder(result.toString()); } else if (targetType == StringBuffer.class) { return new StringBuffer(result.toString()); } // convert the Timestamp type into other time / date types else if (targetType == Calendar.class && (result_class == Timestamp.class || result instanceof Timestamp)) { Calendar cal = Calendar.getInstance(); cal.setTime((Timestamp)result); return cal; } else if (targetType == Date.class && (result_class == Timestamp.class || result instanceof Timestamp)) { return new Date(((Timestamp)result).getTime()); } else if (targetType == java.sql.Date.class && (result_class == Timestamp.class || result instanceof Timestamp)) { return new java.sql.Date(((Timestamp)result).getTime()); } else if (targetType == Time.class && (result_class == Timestamp.class || result instanceof Timestamp)) { return new Time(((Timestamp)result).getTime()); } // convert the java.sql.Date type into other time / date types else if (targetType == Calendar.class && result_class == java.sql.Date.class) { Calendar cal = Calendar.getInstance(); cal.setTime((java.sql.Date)result); return cal; } else if (targetType == Date.class && result_class == java.sql.Date.class) { return new Date(((java.sql.Date)result).getTime()); } else if (targetType == Time.class && result_class == java.sql.Date.class) { return new Time(((java.sql.Date)result).getTime()); } else if (targetType == Timestamp.class && result_class == java.sql.Date.class) { return new Timestamp(((java.sql.Date)result).getTime()); } // convert the Time type into other time / date types else if (targetType == Calendar.class && result_class == Time.class) { Calendar cal = Calendar.getInstance(); cal.setTime((Time)result); return cal; } else if (targetType == Date.class && result_class == Time.class) { return new Date(((Time)result).getTime()); } else if (targetType == java.sql.Date.class && result_class == Time.class) { return new java.sql.Date(((Time)result).getTime()); } else if (targetType == Timestamp.class && result_class == Time.class) { return new Timestamp(((Time)result).getTime()); } else if (targetType == byte[].class && Blob.class.isAssignableFrom(result_class)) { Blob blob = (Blob)result; return FileUtils.readBytes(blob.getBinaryStream()); } else if (targetType == byte[].class && InputStream.class.isAssignableFrom(result_class)) { return FileUtils.readBytes((InputStream)result); } else { if (JavaSpecificationUtils.isAtLeastJdk15()) { if (targetType.isEnum()) { return Enum.valueOf(targetType, result.toString()); } else { return CommonJdk15.getTypedObject(result, targetType); } } return null; } } catch (NumberFormatException e) { throw new DatabaseException("Impossible to convert the result type '" + result_class.getName() + "' with value '" + result.toString() + "' to the target type '" + targetType.getName() + "'.", e); } } } else { return result; } } catch (Throwable e) { throw new DatabaseException("Unexpected exception while obtaining a type object for object '" + result + "' for target type '" + targetType.getName() + "'", e); } } public void setTypedParameter(DbPreparedStatement statement, int parameterIndex, Class targetType, String name, Object value, Constrained constrained) throws DatabaseException { if (null == statement) throw new IllegalArgumentException("statement can't be null."); if (parameterIndex < 1) throw new IllegalArgumentException("parameterIndex must be at least 1."); if (null == targetType) throw new IllegalArgumentException("targetType can't be null."); if (targetType == String.class || targetType == StringBuffer.class) { if (null == value) { statement.setNull(parameterIndex, Types.VARCHAR); } else { if (constrained != null) { ConstrainedProperty property = constrained.getConstrainedProperty(name); if (property != null && !property.hasMaxLength()) { String string_value = value.toString(); statement.setCharacterStream(parameterIndex, new StringReader(string_value), string_value.length()); } else { statement.setString(parameterIndex, value.toString()); } } else { statement.setString(parameterIndex, value.toString()); } } } else if (targetType == Character.class || targetType == char.class) { if (null == value) { statement.setNull(parameterIndex, Types.CHAR); } else { statement.setString(parameterIndex, value.toString()); } } else if (targetType == Time.class || Time.class.isAssignableFrom(targetType)) { if (null == value) { statement.setNull(parameterIndex, Types.TIME); } else { statement.setTime(parameterIndex, (Time)value); } } else if (targetType == java.sql.Date.class || java.sql.Date.class.isAssignableFrom(targetType)) { if (null == value) { statement.setNull(parameterIndex, Types.DATE); } else { statement.setDate(parameterIndex, (java.sql.Date)value); } } else if (targetType == Date.class || Date.class.isAssignableFrom(targetType)) { if (null == value) { statement.setNull(parameterIndex, Types.TIMESTAMP); } else { statement.setTimestamp(parameterIndex, new java.sql.Timestamp(((Date)value).getTime())); } } else if (targetType == Calendar.class || Calendar.class.isAssignableFrom(targetType)) { if (null == value) { statement.setNull(parameterIndex, Types.TIMESTAMP); } else { statement.setTimestamp(parameterIndex, new java.sql.Timestamp(((Calendar)value).getTime().getTime())); } } else if (targetType == Timestamp.class || Timestamp.class.isAssignableFrom(targetType)) { if (null == value) { statement.setNull(parameterIndex, Types.TIMESTAMP); } else { statement.setTimestamp(parameterIndex, (Timestamp)value); } } // make sure that the Boolean type is correctly caught else if (targetType == Boolean.class || targetType == boolean.class) { if (null == value) { statement.setNull(parameterIndex, Types.BOOLEAN); } else { statement.setBoolean(parameterIndex, ((Boolean)value).booleanValue()); } } // make sure that the Integer types are correctly caught else if (targetType == Byte.class || targetType == byte.class) { if (null == value) { statement.setNull(parameterIndex, Types.TINYINT); } else { statement.setByte(parameterIndex, ((Byte)value).byteValue()); } } else if (targetType == Short.class || targetType == short.class) { if (null == value) { statement.setNull(parameterIndex, Types.SMALLINT); } else { statement.setShort(parameterIndex, ((Short)value).shortValue()); } } else if (targetType == Integer.class || targetType == int.class) { if (null == value) { statement.setNull(parameterIndex, Types.INTEGER); } else { statement.setInt(parameterIndex, ((Integer)value).intValue()); } } else if (targetType == Long.class || targetType == long.class) { if (null == value) { statement.setNull(parameterIndex, Types.BIGINT); } else { statement.setLong(parameterIndex, ((Long)value).longValue()); } } // make sure that the Float types are correctly caught else if (targetType == Float.class || targetType == float.class) { if (null == value) { statement.setNull(parameterIndex, Types.FLOAT); } else { statement.setFloat(parameterIndex, ((Float)value).floatValue()); } } else if (targetType == Double.class || targetType == double.class) { if (null == value) { statement.setNull(parameterIndex, Types.DOUBLE); } else { statement.setDouble(parameterIndex, ((Double)value).doubleValue()); } } else if (targetType == BigDecimal.class || BigDecimal.class.isAssignableFrom(targetType)) { if (null == value) { statement.setNull(parameterIndex, Types.NUMERIC); } else { statement.setBigDecimal(parameterIndex, (BigDecimal)value); } } else if (targetType == byte[].class) { if (null == value) { statement.setNull(parameterIndex, Types.ARRAY); } else { statement.setBytes(parameterIndex, (byte[])value); } } else { if (JavaSpecificationUtils.isAtLeastJdk15()) { if (targetType.isEnum()) { if (null == value) { statement.setNull(parameterIndex, Types.VARCHAR); } else { statement.setString(parameterIndex, value.toString()); } } else { if (CommonJdk15.setTypedParameter(statement, parameterIndex, targetType, name, value, constrained)) { return; } throw new DatabaseException("Setting a typed parameter is not supported for index '" + parameterIndex + "', target type '" + targetType.getName() + " and value '" + value + "'."); } } } } public String handleCommonSqlType(Class type, int precision, int scale) { if (JavaSpecificationUtils.isAtLeastJdk15()) { if (type.isEnum()) { return "VARCHAR(255)"; } else { return CommonJdk15.getSqlType(type, precision, scale); } } return null; } }