[hibernate-commits] Hibernate SVN: r15430 - in core/branches/Branch_3_2: src/org/hibernate and 9 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Oct 29 01:38:55 EDT 2008


Author: gbadner
Date: 2008-10-29 01:38:54 -0400 (Wed, 29 Oct 2008)
New Revision: 15430

Added:
   core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateExceptionConverterJDBC4.java
   core/branches/Branch_3_2/src/org/hibernate/exception/TransactionRollbackException.java
   core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapperProxy.java
   core/branches/Branch_3_2/src/org/hibernate/lob/BlobImplProxy.java
   core/branches/Branch_3_2/src/org/hibernate/lob/ClobImplProxy.java
   core/branches/Branch_3_2/src/org/hibernate/lob/LobCreator.java
   core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorFactory.java
   core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC3.java
   core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC4.java
   core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlobProxy.java
   core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClobProxy.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobFromLobCreatorTest.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobTest.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobFromLobCreatorTest.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobTest.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorDefaultTest.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3ConnRelOnCloseTest.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3Test.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4ConnRelOnCloseTest.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4Test.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorDefaultTest.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3ConnRelOnCloseTest.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3Test.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4ConnRelOnCloseTest.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4Test.java
Removed:
   core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapper.java
Modified:
   core/branches/Branch_3_2/etc/log4j.properties
   core/branches/Branch_3_2/src/org/hibernate/Hibernate.java
   core/branches/Branch_3_2/src/org/hibernate/cfg/Environment.java
   core/branches/Branch_3_2/src/org/hibernate/cfg/Settings.java
   core/branches/Branch_3_2/src/org/hibernate/cfg/SettingsFactory.java
   core/branches/Branch_3_2/src/org/hibernate/dialect/Dialect.java
   core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateConverter.java
   core/branches/Branch_3_2/src/org/hibernate/jdbc/ColumnNameCache.java
   core/branches/Branch_3_2/src/org/hibernate/loader/Loader.java
   core/branches/Branch_3_2/src/org/hibernate/lob/BlobImpl.java
   core/branches/Branch_3_2/src/org/hibernate/lob/ClobImpl.java
   core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlob.java
   core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClob.java
   core/branches/Branch_3_2/src/org/hibernate/type/BlobType.java
   core/branches/Branch_3_2/src/org/hibernate/type/ClobType.java
   core/branches/Branch_3_2/test/org/hibernate/test/AllTests.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobTest.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobTest.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/LobHolder.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/MaterializedBlobType.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableData.java
   core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableTypeTest.java
Log:
HHH-2412 : Make Hibernate compilable with JDK 1.6


Modified: core/branches/Branch_3_2/etc/log4j.properties
===================================================================
--- core/branches/Branch_3_2/etc/log4j.properties	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/etc/log4j.properties	2008-10-29 05:38:54 UTC (rev 15430)
@@ -21,11 +21,11 @@
 #log4j.logger.org.hibernate.hql.ast.AST=debug
 
 ### log just the SQL
-#log4j.logger.org.hibernate.SQL=debug
+log4j.logger.org.hibernate.SQL=debug
 
 ### log JDBC bind parameters ###
-log4j.logger.org.hibernate.type=info
-#log4j.logger.org.hibernate.type=debug
+#log4j.logger.org.hibernate.type=info
+log4j.logger.org.hibernate.type=debug
 
 ### log schema export/update ###
 log4j.logger.org.hibernate.tool.hbm2ddl=debug

Modified: core/branches/Branch_3_2/src/org/hibernate/Hibernate.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/Hibernate.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/Hibernate.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -14,10 +14,8 @@
 import org.hibernate.engine.HibernateIterator;
 import org.hibernate.intercept.FieldInterceptionHelper;
 import org.hibernate.intercept.FieldInterceptor;
-import org.hibernate.lob.BlobImpl;
-import org.hibernate.lob.ClobImpl;
-import org.hibernate.lob.SerializableBlob;
-import org.hibernate.lob.SerializableClob;
+import org.hibernate.lob.LobCreator;
+import org.hibernate.lob.LobCreatorFactory;
 import org.hibernate.proxy.HibernateProxy;
 import org.hibernate.proxy.LazyInitializer;
 import org.hibernate.type.AnyType;
@@ -348,13 +346,30 @@
 	}
 
 	/**
+	 * If the setting for Environment#USE_CONNECTION_FOR_LOB_CREATION is true, then the
+	 * returned LobCreator will use the Connection to create LOBs. If it is false, then
+	 * the returned LobCreator will not use the Connection to create LOBs.
+	 *
+	 * If the property is not set, then the returned LobCreator will use the connection to
+	 * create LOBs only if the JVM and JDBC driver support this JDBC4 functionality.
+	 *
+	 * (@see Environment#USE_CONNECTION_FOR_LOB_CREATION)
+	 *
+	 * @param session The session.
+	 * @return the LobCreator
+	 */
+	public static LobCreator getLobCreator(Session session) {
+		return LobCreatorFactory.createLobCreator( session );
+	}
+
+	/**
 	 * Create a new <tt>Blob</tt>. The returned object will be initially immutable.
 	 *
 	 * @param bytes a byte array
 	 * @return the Blob
 	 */
 	public static Blob createBlob(byte[] bytes) {
-		return new SerializableBlob( new BlobImpl( bytes ) );
+		return LobCreatorFactory.createLobCreator().createBlob( bytes );
 	}
 
 	/**
@@ -364,8 +379,8 @@
 	 * @param length the number of bytes in the stream
 	 * @return the Blob
 	 */
-	public static Blob createBlob(InputStream stream, int length) {
-		return new SerializableBlob( new BlobImpl( stream, length ) );
+	public static Blob createBlob(InputStream stream, int length) throws HibernateException, IOException {
+		return LobCreatorFactory.createLobCreator().createBlob( stream, length );
 	}
 
 	/**
@@ -375,8 +390,8 @@
 	 * @return the Blob
 	 * @throws IOException
 	 */
-	public static Blob createBlob(InputStream stream) throws IOException {
-		return new SerializableBlob( new BlobImpl( stream, stream.available() ) );
+	public static Blob createBlob(InputStream stream) throws HibernateException, IOException {
+		return LobCreatorFactory.createLobCreator().createBlob( stream, stream.available() );
 	}
 
 	/**
@@ -384,8 +399,8 @@
 	 *
 	 * @param string a <tt>String</tt>
 	 */
-	public static Clob createClob(String string) {
-		return new SerializableClob( new ClobImpl( string ) );
+	public static Clob createClob(String string) throws HibernateException {
+		return LobCreatorFactory.createLobCreator().createClob( string );
 	}
 
 	/**
@@ -394,8 +409,8 @@
 	 * @param reader a character stream
 	 * @param length the number of characters in the stream
 	 */
-	public static Clob createClob(Reader reader, int length) {
-		return new SerializableClob( new ClobImpl( reader, length ) );
+	public static Clob createClob(Reader reader, int length) throws HibernateException, IOException {
+		return LobCreatorFactory.createLobCreator().createClob( reader, length );
 	}
 
 	/**

Modified: core/branches/Branch_3_2/src/org/hibernate/cfg/Environment.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/cfg/Environment.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/cfg/Environment.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -111,11 +111,16 @@
  *   this property when using user supplied connections)</td>
  * </tr>
  * <tr>
- *   <td><tt>hibernate.jdbc.use_getGeneratedKeys</tt></td>
+ *   <td><tt>hibernate.jdbc.use_get_generated_keys</tt></td>
  *   <td>enable use of JDBC3 PreparedStatement.getGeneratedKeys() to retrieve
  *   natively generated keys after insert. Requires JDBC3+ driver and JRE1.4+</td>
  * </tr>
  * <tr>
+ *   <td><tt>hibernate.jdbc.use_connection_for_lob_creation</tt></td>
+ *   <td>enable use of JDBC4 Connection.createBlob() and Connection.createClob() to
+ *   create Blobs and Clobs. Requires JDBC4+ driver and JRE1.6+</td>
+ * </tr>
+ * <tr>
  *   <td><tt>hibernate.hbm2ddl.auto</tt></td>
  *   <td>enable auto DDL export</td>
  * </tr>
@@ -262,6 +267,13 @@
 	 */
 	public static final String USE_GET_GENERATED_KEYS = "hibernate.jdbc.use_get_generated_keys";
 	/**
+	 * Tells the JDBC driver to attempt to create Blobs and Clobs using JDBC 4.0
+	 * Connection.createBlob() and Connection.createClob(), respectively.
+	 * Performance may be better if this property is set to true and the underlying JDBC driver
+	 * supports these Connection methods.
+	 */
+	public static final String USE_CONNECTION_FOR_LOB_CREATION = "hibernate.jdbc.use_connection_for_lob_creation";
+	/**
 	 * Gives the JDBC driver a hint as to the number of rows that should be fetched from the database
 	 * when more rows are needed. If <tt>0</tt>, JDBC driver default settings will be used.
 	 */
@@ -478,6 +490,7 @@
 	private static final boolean JVM_HAS_TIMESTAMP_BUG;
 	private static final boolean JVM_HAS_JDK14_TIMESTAMP;
 	private static final boolean JVM_SUPPORTS_GET_GENERATED_KEYS;
+	private static final boolean JVM_SUPPORTS_JDBC4;
 
 	private static final Properties GLOBAL_PROPERTIES;
 	private static final HashMap ISOLATION_LEVELS = new HashMap();
@@ -578,6 +591,18 @@
 		JVM_SUPPORTS_GET_GENERATED_KEYS = getGeneratedKeysSupport;
 		if (!JVM_SUPPORTS_GET_GENERATED_KEYS) log.info("JVM does not support Statement.getGeneratedKeys()");
 
+		boolean jvmSupportsJDBC4;
+		try {
+			Connection.class.getMethod("createBlob", null);
+			Connection.class.getMethod("createClob", null);
+			jvmSupportsJDBC4 = true;
+		}
+		catch (NoSuchMethodException nsme) {
+			jvmSupportsJDBC4 = false;
+		}
+		JVM_SUPPORTS_JDBC4 = jvmSupportsJDBC4;
+		if (!JVM_SUPPORTS_JDBC4 ) log.info("JVM does not support JDBC4");
+
 		boolean linkedHashSupport;
 		try {
 			Class.forName("java.util.LinkedHashSet");
@@ -633,6 +658,10 @@
 		return JVM_SUPPORTS_GET_GENERATED_KEYS;
 	}
 
+	public static boolean jvmSupportsJDBC4() {
+		return JVM_SUPPORTS_JDBC4;
+	}
+
 	/**
 	 * Should we use streams to bind binary types to JDBC IN parameters.
 	 * Property <tt>hibernate.jdbc.use_streams_for_binary</tt>.

Modified: core/branches/Branch_3_2/src/org/hibernate/cfg/Settings.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/cfg/Settings.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/cfg/Settings.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -32,6 +32,7 @@
 	private int defaultBatchFetchSize;
 	private boolean scrollableResultSetsEnabled;
 	private boolean getGeneratedKeysEnabled;
+	private boolean useConnectionForLobCreationEnabled;
 	private String defaultSchemaName;
 	private String defaultCatalogName;
 	private Integer jdbcFetchSize;
@@ -124,6 +125,10 @@
 		return getGeneratedKeysEnabled;
 	}
 
+	public boolean isUseConnectionForLobCreationEnabled() {
+		return useConnectionForLobCreationEnabled;
+	}
+
 	public boolean isMinimalPutsEnabled() {
 		return minimalPutsEnabled;
 	}
@@ -319,6 +324,10 @@
 		getGeneratedKeysEnabled = b;
 	}
 
+	void setUseConnectionForLobCreationEnabled(boolean b) {
+		useConnectionForLobCreationEnabled = b;		
+	}
+
 	void setJdbcFetchSize(Integer integer) {
 		jdbcFetchSize = integer;
 	}

Modified: core/branches/Branch_3_2/src/org/hibernate/cfg/SettingsFactory.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/cfg/SettingsFactory.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/cfg/SettingsFactory.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -71,6 +71,7 @@
 		boolean metaSupportsBatchUpdates = false;
 		boolean metaReportsDDLCausesTxnCommit = false;
 		boolean metaReportsDDLInTxnSupported = true;
+		boolean driverConnectionHasLobCreationMethods = false;
 
 		// 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value.
 		// The need for it is intended to be alleviated with 3.3 developement, thus it is
@@ -108,7 +109,31 @@
 						}
 					}
 
+					if ( Environment.jvmSupportsJDBC4() ) {
+						try {
+							// this block doesn't actually use the DatabaseMetaData, but it does use the
+							// driver Connection Class to determine if methods are present.
+							Class c = conn.getClass();
+							if ( Connection.class.equals( c.getMethod( "createBlob", null ).getDeclaringClass() ) ||
+								Connection.class.equals( c.getMethod( "createClob", null ).getDeclaringClass() ) ) {
+								driverConnectionHasLobCreationMethods = false;
+							}
+							else {
+								// the driver's Connection class has all three methods;
+								// can't tell if the driver actually supports these methods w/o calling them,
+								// but don't want to actually create a LOB here.
+								driverConnectionHasLobCreationMethods = true;
+							}
+						}
+						catch (AbstractMethodError ame) {
+							driverConnectionHasLobCreationMethods = false;
+						}
+						catch (Exception e) {
+							driverConnectionHasLobCreationMethods = false;
+						}
+					}
 				}
+
 				finally {
 					connections.closeConnection(conn);
 				}
@@ -170,6 +195,10 @@
 		log.info("JDBC3 getGeneratedKeys(): " + enabledDisabled(useGetGeneratedKeys) );
 		settings.setGetGeneratedKeysEnabled(useGetGeneratedKeys);
 
+		boolean useConnectionForLobCreation = PropertiesHelper.getBoolean(Environment.USE_CONNECTION_FOR_LOB_CREATION, properties, driverConnectionHasLobCreationMethods);
+		log.info("JDBC4 Connection.createBlob() and Connection.createClob(): " + enabledDisabled(useConnectionForLobCreation) );
+		settings.setUseConnectionForLobCreationEnabled(useConnectionForLobCreation);
+
 		Integer statementFetchSize = PropertiesHelper.getInteger(Environment.STATEMENT_FETCH_SIZE, properties);
 		if (statementFetchSize!=null) log.info("JDBC result set fetch size: " + statementFetchSize);
 		settings.setJdbcFetchSize(statementFetchSize);

Modified: core/branches/Branch_3_2/src/org/hibernate/dialect/Dialect.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/dialect/Dialect.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/dialect/Dialect.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -1,4 +1,27 @@
 //$Id$
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
 package org.hibernate.dialect;
 
 import java.sql.CallableStatement;
@@ -29,6 +52,7 @@
 import org.hibernate.exception.SQLExceptionConverter;
 import org.hibernate.exception.SQLStateConverter;
 import org.hibernate.exception.ViolatedConstraintNameExtracter;
+import org.hibernate.exception.SQLStateExceptionConverterJDBC4;
 import org.hibernate.id.IdentityGenerator;
 import org.hibernate.id.SequenceGenerator;
 import org.hibernate.id.TableHiLoGenerator;
@@ -1181,9 +1205,14 @@
 	 */
 	public SQLExceptionConverter buildSQLExceptionConverter() {
 		// The default SQLExceptionConverter for all dialects is based on SQLState
-		// since SQLErrorCode is extremely vendor-specific.  Specific Dialects
+		// since SQLErrorCode is extremely vendor-specific.  If JDBC4 is supported,
+		// then the default SQLExceptionConverter will convert based on JDBC4
+		// SQLException if the SQLState is not recognized. Specific Dialects
 		// may override to return whatever is most appropriate for that vendor.
-		return new SQLStateConverter( getViolatedConstraintNameExtracter() );
+		return ( Environment.jvmSupportsJDBC4() ?
+				new SQLStateExceptionConverterJDBC4( getViolatedConstraintNameExtracter() ) :
+				new SQLStateConverter( getViolatedConstraintNameExtracter() )
+		);
 	}
 
 	private static final ViolatedConstraintNameExtracter EXTRACTER = new ViolatedConstraintNameExtracter() {

Modified: core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateConverter.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateConverter.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateConverter.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -24,6 +24,7 @@
 	private static final Set DATA_CATEGORIES = new HashSet();
 	private static final Set INTEGRITY_VIOLATION_CATEGORIES = new HashSet();
 	private static final Set CONNECTION_CATEGORIES = new HashSet();
+	private static final Set TRANSACTION_ROLLBACK_CATEGORIES = new HashSet();
 
 	static {
 		SQL_GRAMMAR_CATEGORIES.add( "07" );
@@ -42,12 +43,19 @@
 		INTEGRITY_VIOLATION_CATEGORIES.add( "44" );
 
 		CONNECTION_CATEGORIES.add( "08" );
+		CONNECTION_CATEGORIES.add( "28" );
+
+		TRANSACTION_ROLLBACK_CATEGORIES.add( "40" );
 	}
 
 	public SQLStateConverter(ViolatedConstraintNameExtracter extracter) {
 		this.extracter = extracter;
 	}
 
+	protected String getViolatedConstraintName(SQLException sqlException) {
+		return extracter.extractConstraintName( sqlException );
+	}
+
 	/**
 	 * Convert the given SQLException into Hibernate's JDBCException hierarchy.
 	 *
@@ -67,7 +75,7 @@
 					return new SQLGrammarException( message, sqlException, sql );
 				}
 				else if ( INTEGRITY_VIOLATION_CATEGORIES.contains( sqlStateClassCode ) ) {
-					String constraintName = extracter.extractConstraintName( sqlException );
+					String constraintName = getViolatedConstraintName( sqlException );
 					return new ConstraintViolationException( message, sqlException, sql, constraintName );
 				}
 				else if ( CONNECTION_CATEGORIES.contains( sqlStateClassCode ) ) {
@@ -76,6 +84,9 @@
 				else if ( DATA_CATEGORIES.contains( sqlStateClassCode ) ) {
 					return new DataException( message, sqlException, sql );
 				}
+				else if ( TRANSACTION_ROLLBACK_CATEGORIES.contains( sqlStateClassCode ) ) {
+					return new TransactionRollbackException( message, sqlException, sql );
+				}
 			}
 
 			if ( "40001".equals( sqlState ) ) {

Added: core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateExceptionConverterJDBC4.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateExceptionConverterJDBC4.java	                        (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateExceptionConverterJDBC4.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,87 @@
+// $Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.exception;
+
+import org.hibernate.JDBCException;
+
+import java.sql.SQLException;
+
+/**
+ * A SQLExceptionConverter implementation which performs converion based on
+ * the underlying SQLState. Interpretation of a SQL error based on SQLState
+ * is not nearly as accurate as using the ErrorCode (which is, however, vendor-
+ * specific).  Use of a ErrorCode-based converter should be preferred approach
+ * for converting/interpreting SQLExceptions.
+ *
+ * @author Gail Badner
+ */
+public class SQLStateExceptionConverterJDBC4 extends SQLStateConverter {
+
+	public SQLStateExceptionConverterJDBC4(ViolatedConstraintNameExtracter extracter) {
+		super( extracter );
+	}
+
+	/**
+	 * Convert the given SQLException into Hibernate's JDBCException hierarchy.
+	 *
+	 * @param sqlException The SQLException to be converted.
+	 * @param message      An optional error message.
+	 * @param sql          Optionally, the sql being performed when the exception occurred.
+	 * @return The resulting JDBCException.
+	 */
+	public JDBCException convert(SQLException sqlException, String message, String sql) {
+		JDBCException jdbcException = super.convert( sqlException, message, sql );
+		if ( !( jdbcException instanceof GenericJDBCException) ) {
+			return jdbcException;
+		}
+
+		try {
+			if ( Class.forName( "java.sql.SQLIntegrityConstraintViolationException" ).isInstance( sqlException ) ) {
+				String constraintName = getViolatedConstraintName( sqlException );
+				return new ConstraintViolationException( message, sqlException, sql, constraintName );
+			}
+			else if ( Class.forName( "java.sql.SQLTransactionRollbackException" ).isInstance( sqlException ) ) {
+				return new TransactionRollbackException( message, sqlException, sql );
+			}
+			else if ( Class.forName( "java.sql.SQLClientInfoException" ).isInstance( sqlException ) ||
+					Class.forName( "java.sql.SQLInvalidAuthorizationSpecException" ).isInstance( sqlException ) ||
+					Class.forName( "java.sql.SQLNonTransientConnectionException" ).isInstance( sqlException ) ||
+					Class.forName( "java.sql.SQLTransientConnectionException" ).isInstance( sqlException ) ) {
+				return new JDBCConnectionException( message, sqlException, sql );
+			}
+			else if ( Class.forName( "java.sql.SQLSyntaxErrorException" ).isInstance( sqlException ) ) {
+				return new SQLGrammarException( message, sqlException, sql );
+			}
+			else if ( Class.forName( "java.sql.SQLDataException" ).isInstance( sqlException ) ||
+					Class.forName( "javax.sql.rowset.serial.SerialException" ).isInstance( sqlException ) ) {
+				return new DataException( message, sqlException, sql );
+			}
+		}
+		catch ( ClassNotFoundException e ) {
+			// log because either config is messed up or there's a typo in a class name
+		}
+		return jdbcException;
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/src/org/hibernate/exception/TransactionRollbackException.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/exception/TransactionRollbackException.java	                        (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/exception/TransactionRollbackException.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,59 @@
+// $Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.exception;
+
+import org.hibernate.JDBCException;
+
+import java.sql.SQLException;
+
+/**
+ * Implementation of JDBCException that indicates that the current statement
+ * was automatically rolled back by the database becuase of deadlock or other
+ * transaction serialization failures.
+ *
+ * @author Gail Badner
+ */
+public class TransactionRollbackException extends JDBCException {
+	/**
+	 * Constructor for TransactionRollbackException.
+	 *
+	 * @param message Optional message.
+	 * @param root    The underlying exception.
+	 */
+	public TransactionRollbackException(String message, SQLException root) {
+		super( message, root );
+	}
+
+	/**
+	 * Constructor for TransactionRollbackException.
+	 *
+	 * @param message Optional message.
+	 * @param root    The underlying exception.
+	 * @param sql     the SQL statement involved in the exception.
+	 */
+	public TransactionRollbackException(String message, SQLException root, String sql) {
+		super( message, root, sql );
+	}
+}
\ No newline at end of file

Modified: core/branches/Branch_3_2/src/org/hibernate/jdbc/ColumnNameCache.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/jdbc/ColumnNameCache.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/jdbc/ColumnNameCache.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -1,7 +1,31 @@
 // $Id$
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
 package org.hibernate.jdbc;
 
 import java.sql.SQLException;
+import java.sql.ResultSet;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -19,13 +43,13 @@
 		this.columnNameToIndexCache = new HashMap( columnCount );
 	}
 
-	public int getIndexForColumnName(String columnName, ResultSetWrapper rs)throws SQLException {
+	public int getIndexForColumnName(String columnName, ResultSet rs) throws SQLException {
 		Integer cached = ( Integer ) columnNameToIndexCache.get( columnName );
 		if ( cached != null ) {
 			return cached.intValue();
 		}
 		else {
-			int index = rs.getTarget().findColumn( columnName );
+			int index = rs.findColumn( columnName );
 			columnNameToIndexCache.put( columnName, new Integer(index) );
 			return index;
 		}

Deleted: core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapper.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapper.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapper.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -1,619 +0,0 @@
-// $Id$
-package org.hibernate.jdbc;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URL;
-import java.sql.Array;
-import java.sql.Blob;
-import java.sql.Clob;
-import java.sql.Date;
-import java.sql.Ref;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-import java.sql.Statement;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.util.Calendar;
-import java.util.Map;
-
-/**
- * A ResultSet delegate, responsible for locally caching the columnName-to-columnIndex
- * resolution that has been found to be inefficient in a few vendor's drivers (i.e., Oracle
- * and Postgres).
- *
- * @author Steve Ebersole
- */
-public class ResultSetWrapper implements ResultSet {
-
-	private ResultSet rs;
-	private ColumnNameCache columnNameCache;
-
-	public ResultSetWrapper(ResultSet resultSet, ColumnNameCache columnNameCache) {
-		this.rs = resultSet;
-		this.columnNameCache = columnNameCache;
-	}
-
-	/*package*/ ResultSet getTarget() {
-		return rs;
-	}
-
-
-	// ResultSet impl ("overridden") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-	/**
-	 * Overridden version to utilize local caching of the column indexes by name
-	 * to improve performance for those drivers which are known to not support
-	 * such caching by themselves.
-	 * <p/>
-	 * This implementation performs the caching based on the upper case version
-	 * of the given column name.
-	 *
-	 * @param columnName The column name to resolve into an index.
-	 * @return The column index corresponding to the given column name.
-	 * @throws SQLException - if the ResultSet object does not contain
-	 * columnName or a database access error occurs
-	 */
-	public int findColumn(String columnName) throws SQLException {
-		return columnNameCache.getIndexForColumnName( columnName, this );
-	}
-
-	public Array getArray(String colName) throws SQLException {
-		return rs.getArray( findColumn(colName) );
-	}
-
-	public void updateArray(String columnName, Array x) throws SQLException {
-		rs.updateArray( findColumn(columnName), x );
-	}
-
-	public InputStream getAsciiStream(String columnName) throws SQLException {
-		return rs.getAsciiStream( findColumn(columnName) );
-	}
-
-	public void updateAsciiStream(String columnName, InputStream x, int length) throws SQLException {
-		rs.updateAsciiStream( findColumn(columnName), x, length );
-	}
-
-	public BigDecimal getBigDecimal(String columnName) throws SQLException {
-		return rs.getBigDecimal( findColumn(columnName) );
-	}
-
-	public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
-		return rs.getBigDecimal( findColumn(columnName), scale );
-	}
-
-	public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
-		rs.updateBigDecimal( findColumn(columnName), x );
-	}
-
-	public InputStream getBinaryStream(String columnName) throws SQLException {
-		return rs.getBinaryStream( findColumn(columnName) );
-	}
-
-	public void updateBinaryStream(String columnName, InputStream x, int length) throws SQLException {
-		rs.updateBinaryStream( findColumn(columnName), x, length );
-	}
-
-	public Blob getBlob(String columnName) throws SQLException {
-		return rs.getBlob( findColumn(columnName) );
-	}
-
-	public void updateBlob(String columnName, Blob x) throws SQLException {
-		rs.updateBlob( findColumn(columnName), x );
-	}
-
-	public boolean getBoolean(String columnName) throws SQLException {
-		return rs.getBoolean( findColumn(columnName) );
-	}
-
-	public void updateBoolean(String columnName, boolean x) throws SQLException {
-		rs.updateBoolean( findColumn(columnName), x );
-	}
-
-	public byte getByte(String columnName) throws SQLException {
-		return rs.getByte( findColumn(columnName) );
-	}
-
-	public void updateByte(String columnName, byte x) throws SQLException {
-		rs.updateByte( findColumn(columnName), x );
-	}
-
-	public byte[] getBytes(String columnName) throws SQLException {
-		return rs.getBytes( findColumn(columnName) );
-	}
-
-	public void updateBytes(String columnName, byte[] x) throws SQLException {
-		rs.updateBytes( findColumn(columnName), x );
-	}
-
-	public Reader getCharacterStream(String columnName) throws SQLException {
-		return rs.getCharacterStream( findColumn(columnName) );
-	}
-
-	public void updateCharacterStream(String columnName, Reader x, int length) throws SQLException {
-		rs.updateCharacterStream( findColumn(columnName), x, length );
-	}
-
-	public Clob getClob(String columnName) throws SQLException {
-		return rs.getClob( findColumn(columnName) );
-	}
-
-	public void updateClob(String columnName, Clob x) throws SQLException {
-		rs.updateClob( findColumn(columnName), x );
-	}
-
-	public Date getDate(String columnName) throws SQLException {
-		return rs.getDate( findColumn(columnName) );
-	}
-
-	public Date getDate(String columnName, Calendar cal) throws SQLException {
-		return rs.getDate( findColumn(columnName), cal );
-	}
-
-	public void updateDate(String columnName, Date x) throws SQLException {
-		rs.updateDate( findColumn(columnName), x );
-	}
-
-	public double getDouble(String columnName) throws SQLException {
-		return rs.getDouble( findColumn(columnName) );
-	}
-
-	public void updateDouble(String columnName, double x) throws SQLException {
-		rs.updateDouble( findColumn(columnName), x );
-	}
-
-	public float getFloat(String columnName) throws SQLException {
-		return rs.getFloat( findColumn(columnName) );
-	}
-
-	public void updateFloat(String columnName, float x) throws SQLException {
-		rs.updateFloat( findColumn(columnName), x );
-	}
-
-	public int getInt(String columnName) throws SQLException {
-		return rs.getInt( findColumn(columnName) );
-	}
-
-	public void updateInt(String columnName, int x) throws SQLException {
-		rs.updateInt( findColumn(columnName), x );
-	}
-
-	public long getLong(String columnName) throws SQLException {
-		return rs.getLong( findColumn(columnName) );
-	}
-
-	public void updateLong(String columnName, long x) throws SQLException {
-		rs.updateLong( findColumn(columnName), x );
-	}
-
-	public Object getObject(String columnName) throws SQLException {
-		return rs.getObject( findColumn(columnName) );
-	}
-
-	public Object getObject(String columnName, Map map) throws SQLException {
-		return rs.getObject( findColumn(columnName), map );
-	}
-
-	public void updateObject(String columnName, Object x) throws SQLException {
-		rs.updateObject( findColumn(columnName), x );
-	}
-
-	public void updateObject(String columnName, Object x, int scale) throws SQLException {
-		rs.updateObject( findColumn(columnName), x, scale );
-	}
-
-	public Ref getRef(String columnName) throws SQLException {
-		return rs.getRef( findColumn(columnName) );
-	}
-
-	public void updateRef(String columnName, Ref x) throws SQLException {
-		rs.updateRef( findColumn(columnName), x );
-	}
-
-	public short getShort(String columnName) throws SQLException {
-		return rs.getShort( findColumn(columnName) );
-	}
-
-	public void updateShort(String columnName, short x) throws SQLException {
-		rs.updateShort( findColumn(columnName), x );
-	}
-
-	public String getString(String columnName) throws SQLException {
-		return rs.getString( findColumn(columnName) );
-	}
-
-	public void updateString(String columnName, String x) throws SQLException {
-		rs.updateString( findColumn(columnName), x );
-	}
-
-	public Time getTime(String columnName) throws SQLException {
-		return rs.getTime( findColumn(columnName) );
-	}
-
-	public Time getTime(String columnName, Calendar cal) throws SQLException {
-		return rs.getTime( findColumn(columnName), cal );
-	}
-
-	public void updateTime(String columnName, Time x) throws SQLException {
-		rs.updateTime( findColumn(columnName), x );
-	}
-
-	public Timestamp getTimestamp(String columnName) throws SQLException {
-		return rs.getTimestamp( findColumn(columnName) );
-	}
-
-	public void updateTimestamp(String columnName, Timestamp x) throws SQLException {
-		rs.updateTimestamp( findColumn(columnName), x );
-	}
-
-	public Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
-		return rs.getTimestamp( findColumn(columnName), cal );
-	}
-
-	public InputStream getUnicodeStream(String columnName) throws SQLException {
-		return rs.getUnicodeStream( findColumn(columnName) );
-	}
-
-	public URL getURL(String columnName) throws SQLException {
-		return rs.getURL( findColumn(columnName) );
-	}
-
-	public void updateNull(String columnName) throws SQLException {
-		rs.updateNull( findColumn(columnName) );
-	}
-
-
-	// ResultSet impl (delegated) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-	public int getConcurrency() throws SQLException {
-		return rs.getConcurrency();
-	}
-
-	public int getFetchDirection() throws SQLException {
-		return rs.getFetchDirection();
-	}
-
-	public int getFetchSize() throws SQLException {
-		return rs.getFetchSize();
-	}
-
-	public int getRow() throws SQLException {
-		return rs.getRow();
-	}
-
-	public int getType() throws SQLException {
-		return rs.getType();
-	}
-
-	public void afterLast() throws SQLException {
-		rs.afterLast();
-	}
-
-	public void beforeFirst() throws SQLException {
-		rs.beforeFirst();
-	}
-
-	public void cancelRowUpdates() throws SQLException {
-		rs.cancelRowUpdates();
-	}
-
-	public void clearWarnings() throws SQLException {
-		rs.clearWarnings();
-	}
-
-	public void close() throws SQLException {
-		rs.close();
-	}
-
-	public void deleteRow() throws SQLException {
-		rs.deleteRow();
-	}
-
-	public void insertRow() throws SQLException {
-		rs.insertRow();
-	}
-
-	public void moveToCurrentRow() throws SQLException {
-		rs.moveToCurrentRow();
-	}
-
-	public void moveToInsertRow() throws SQLException {
-		rs.moveToInsertRow();
-	}
-
-	public void refreshRow() throws SQLException {
-		rs.refreshRow();
-	}
-
-	public void updateRow() throws SQLException {
-		rs.updateRow();
-	}
-
-	public boolean first() throws SQLException {
-		return rs.first();
-	}
-
-	public boolean isAfterLast() throws SQLException {
-		return rs.isAfterLast();
-	}
-
-	public boolean isBeforeFirst() throws SQLException {
-		return rs.isBeforeFirst();
-	}
-
-	public boolean isFirst() throws SQLException {
-		return rs.isFirst();
-	}
-
-	public boolean isLast() throws SQLException {
-		return rs.isLast();
-	}
-
-	public boolean last() throws SQLException {
-		return rs.last();
-	}
-
-	public boolean next() throws SQLException {
-		return rs.next();
-	}
-
-	public boolean previous() throws SQLException {
-		return rs.previous();
-	}
-
-	public boolean rowDeleted() throws SQLException {
-		return rs.rowDeleted();
-	}
-
-	public boolean rowInserted() throws SQLException {
-		return rs.rowInserted();
-	}
-
-	public boolean rowUpdated() throws SQLException {
-		return rs.rowUpdated();
-	}
-
-	public boolean wasNull() throws SQLException {
-		return rs.wasNull();
-	}
-
-	public byte getByte(int columnIndex) throws SQLException {
-		return rs.getByte(columnIndex);
-	}
-
-	public double getDouble(int columnIndex) throws SQLException {
-		return rs.getDouble(columnIndex);
-	}
-
-	public float getFloat(int columnIndex) throws SQLException {
-		return rs.getFloat(columnIndex);
-	}
-
-	public int getInt(int columnIndex) throws SQLException {
-		return rs.getInt(columnIndex);
-	}
-
-	public long getLong(int columnIndex) throws SQLException {
-		return rs.getLong(columnIndex);
-	}
-
-	public short getShort(int columnIndex) throws SQLException {
-		return rs.getShort(columnIndex);
-	}
-
-	public void setFetchDirection(int direction) throws SQLException {
-		rs.setFetchDirection(direction);
-	}
-
-	public void setFetchSize(int rows) throws SQLException {
-		rs.setFetchSize(rows);
-	}
-
-	public void updateNull(int columnIndex) throws SQLException {
-		rs.updateNull(columnIndex);
-	}
-
-	public boolean absolute(int row) throws SQLException {
-		return rs.absolute(row);
-	}
-
-	public boolean getBoolean(int columnIndex) throws SQLException {
-		return rs.getBoolean(columnIndex);
-	}
-
-	public boolean relative(int rows) throws SQLException {
-		return rs.relative(rows);
-	}
-
-	public byte[] getBytes(int columnIndex) throws SQLException {
-		return rs.getBytes(columnIndex);
-	}
-
-	public void updateByte(int columnIndex, byte x) throws SQLException {
-		rs.updateByte(columnIndex, x);
-	}
-
-	public void updateDouble(int columnIndex, double x) throws SQLException {
-		rs.updateDouble(columnIndex, x);
-	}
-
-	public void updateFloat(int columnIndex, float x) throws SQLException {
-		rs.updateFloat(columnIndex, x);
-	}
-
-	public void updateInt(int columnIndex, int x) throws SQLException {
-		rs.updateInt(columnIndex, x);
-	}
-
-	public void updateLong(int columnIndex, long x) throws SQLException {
-		rs.updateLong(columnIndex, x);
-	}
-
-	public void updateShort(int columnIndex, short x) throws SQLException {
-		rs.updateShort(columnIndex, x);
-	}
-
-	public void updateBoolean(int columnIndex, boolean x) throws SQLException {
-		rs.updateBoolean(columnIndex, x);
-	}
-
-	public void updateBytes(int columnIndex, byte[] x) throws SQLException {
-		rs.updateBytes(columnIndex, x);
-	}
-
-	public InputStream getAsciiStream(int columnIndex) throws SQLException {
-		return rs.getAsciiStream(columnIndex);
-	}
-
-	public InputStream getBinaryStream(int columnIndex) throws SQLException {
-		return rs.getBinaryStream(columnIndex);
-	}
-
-	public InputStream getUnicodeStream(int columnIndex) throws SQLException {
-		return rs.getUnicodeStream(columnIndex);
-	}
-
-	public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException {
-		rs.updateAsciiStream(columnIndex, x, length);
-	}
-
-	public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException {
-		rs.updateBinaryStream(columnIndex, x, length);
-	}
-
-	public Reader getCharacterStream(int columnIndex) throws SQLException {
-		return rs.getCharacterStream(columnIndex);
-	}
-
-	public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException {
-		rs.updateCharacterStream(columnIndex, x, length);
-	}
-
-	public Object getObject(int columnIndex) throws SQLException {
-		return rs.getObject(columnIndex);
-	}
-
-	public void updateObject(int columnIndex, Object x) throws SQLException {
-		rs.updateObject(columnIndex, x);
-	}
-
-	public void updateObject(int columnIndex, Object x, int scale) throws SQLException {
-		rs.updateObject(columnIndex, x, scale);
-	}
-
-	public String getCursorName() throws SQLException {
-		return rs.getCursorName();
-	}
-
-	public String getString(int columnIndex) throws SQLException {
-		return rs.getString(columnIndex);
-	}
-
-	public void updateString(int columnIndex, String x) throws SQLException {
-		rs.updateString(columnIndex, x);
-	}
-
-	public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
-		return rs.getBigDecimal(columnIndex);
-	}
-
-	public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
-		return rs.getBigDecimal(columnIndex, scale);
-	}
-
-	public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
-		rs.updateBigDecimal(columnIndex, x);
-	}
-
-	public URL getURL(int columnIndex) throws SQLException {
-		return rs.getURL(columnIndex);
-	}
-
-	public Array getArray(int columnIndex) throws SQLException {
-		return rs.getArray(columnIndex);
-	}
-
-	public void updateArray(int columnIndex, Array x) throws SQLException {
-		rs.updateArray(columnIndex, x);
-	}
-
-	public Blob getBlob(int columnIndex) throws SQLException {
-		return rs.getBlob(columnIndex);
-	}
-
-	public void updateBlob(int columnIndex, Blob x) throws SQLException {
-		rs.updateBlob(columnIndex, x);
-	}
-
-	public Clob getClob(int columnIndex) throws SQLException {
-		return rs.getClob(columnIndex);
-	}
-
-	public void updateClob(int columnIndex, Clob x) throws SQLException {
-		rs.updateClob(columnIndex, x);
-	}
-
-	public Date getDate(int columnIndex) throws SQLException {
-		return rs.getDate(columnIndex);
-	}
-
-	public void updateDate(int columnIndex, Date x) throws SQLException {
-		rs.updateDate(columnIndex, x);
-	}
-
-	public Ref getRef(int columnIndex) throws SQLException {
-		return rs.getRef(columnIndex);
-	}
-
-	public void updateRef(int columnIndex, Ref x) throws SQLException {
-		rs.updateRef(columnIndex, x);
-	}
-
-	public ResultSetMetaData getMetaData() throws SQLException {
-		return rs.getMetaData();
-	}
-
-	public SQLWarning getWarnings() throws SQLException {
-		return rs.getWarnings();
-	}
-
-	public Statement getStatement() throws SQLException {
-		return rs.getStatement();
-	}
-
-	public Time getTime(int columnIndex) throws SQLException {
-		return rs.getTime(columnIndex);
-	}
-
-	public void updateTime(int columnIndex, Time x) throws SQLException {
-		rs.updateTime(columnIndex, x);
-	}
-
-	public Timestamp getTimestamp(int columnIndex) throws SQLException {
-		return rs.getTimestamp(columnIndex);
-	}
-
-	public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {
-		rs.updateTimestamp(columnIndex, x);
-	}
-
-	public Object getObject(int columnIndex, Map map) throws SQLException {
-		return rs.getObject( columnIndex, map );
-	}
-
-	public Date getDate(int columnIndex, Calendar cal) throws SQLException {
-		return rs.getDate(columnIndex, cal);
-	}
-
-	public Time getTime(int columnIndex, Calendar cal) throws SQLException {
-		return rs.getTime(columnIndex, cal);
-	}
-
-	public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
-		return rs.getTimestamp(columnIndex, cal);
-	}
-}
-

Added: core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapperProxy.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapperProxy.java	                        (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapperProxy.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,170 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.jdbc;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.InvocationTargetException;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.hibernate.util.JDBCExceptionReporter;
+
+/**
+ * A proxy for a ResultSet delegate, responsible for locally caching the
+ * columnName-to-columnIndex resolution that has been found to be inefficient
+ * in a few vendor's drivers (i.e., Oracle and Postgres).
+ *
+ * @author Gail Badner
+ */
+public class ResultSetWrapperProxy implements InvocationHandler {
+
+	private static final Class[] PROXY_INTERFACES = new Class[] { ResultSet.class };
+	private static final Log log = LogFactory.getLog( ResultSetWrapperProxy.class );
+
+	private final ResultSet rs;
+	private ColumnNameCache columnNameCache;
+
+	/**
+	 * Generates a proxy wrapping the ResultSet.
+	 *
+	 * @param resultSet The resultSet to wrap.
+	 * @param columnNameCache The cache storing data for converting column names to column indexes.
+	 * @return The generated proxy.
+	 */
+	public static ResultSet generateProxy(ResultSet resultSet, ColumnNameCache columnNameCache) {
+		return ( ResultSet ) Proxy.newProxyInstance(
+				getProxyClassLoader(),
+				PROXY_INTERFACES,
+				new ResultSetWrapperProxy( resultSet, columnNameCache )
+		);
+	}
+
+	private ResultSetWrapperProxy(ResultSet resultSet, ColumnNameCache columnNameCache) {
+		this.rs = resultSet;
+		this.columnNameCache = columnNameCache;
+	}
+
+	/**
+	 * Overridden version to utilize local caching of the column indexes by name
+	 * to improve performance for those drivers which are known to not support
+	 * such caching by themselves.
+	 * <p/>
+	 * This implementation performs the caching based on the upper case version
+	 * of the given column name.
+	 *
+	 * @param columnName The column name to resolve into an index.
+	 * @return The column index corresponding to the given column name.
+	 * @throws java.sql.SQLException - if the ResultSet object does not contain
+	 * columnName or a database access error occurs
+	 */
+	public int findColumn(String columnName) throws SQLException {
+		return columnNameCache.getIndexForColumnName( columnName, rs );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+		if ( isFirstArgColumnLabel( method, args ) ) {
+			try {
+				int columnIndex = findColumn( ( String ) args[0] );
+				return invokeMethod( getMethodUsingColumnIndex( method ), getArgsUsingColumnIndex( args, columnIndex ) );
+			}
+			catch ( SQLException ex ) {
+				StringBuffer buf = new StringBuffer()
+						.append( "Exception getting column index for column: [" )
+						.append( args[0] )
+						.append( "].\nReverting to using: [" )
+						.append( args[ 0 ] )
+						.append( "] as first argument for method: [" )
+						.append( method )
+						.append( "]" );
+				JDBCExceptionReporter.logExceptions( ex, buf.toString() );
+			}
+			catch ( NoSuchMethodException ex ) {
+				StringBuffer buf = new StringBuffer()
+						.append( "Exception switching from method: [" )
+						.append( method )
+						.append( "] to a method using the column index. Reverting to using: [" )
+						.append( method )
+						.append( "]" );
+				if ( log.isWarnEnabled() ) {
+					log.warn( buf.toString() );
+				}
+			}
+		}
+		return invokeMethod( method, args );
+	}
+
+	private boolean isFirstArgColumnLabel(Method method, Object args[]) {
+		return method.getParameterTypes().length > 0 &&
+				method.getParameterTypes()[ 0 ].equals( String.class ) &&
+				args.length == method.getParameterTypes().length &&
+				String.class.isInstance( args[ 0 ] ) &&
+				( method.getName().startsWith( "get" ) || method.getName().startsWith( "update" ) );
+	}
+
+	private Method getMethodUsingColumnIndex(Method method) throws NoSuchMethodException {
+		Class actualParameterTypes[] = new Class[ method.getParameterTypes().length ];
+		actualParameterTypes[0] = int.class;
+		System.arraycopy( method.getParameterTypes(), 1, actualParameterTypes, 1, method.getParameterTypes().length - 1 );
+		return method.getDeclaringClass().getMethod( method.getName(), actualParameterTypes );
+	}
+
+	private Object[] getArgsUsingColumnIndex( Object[] args, int columnIndex ) {
+		Object actualArgs[] = new Object[ args.length ];
+		actualArgs[0] = new Integer( columnIndex );
+		System.arraycopy( args, 1, actualArgs, 1, args.length - 1 );
+	    return actualArgs;
+	}
+
+	private Object invokeMethod( Method method, Object args[] ) throws Throwable {
+		try {
+			return method.invoke( rs, args );
+		}
+		catch( InvocationTargetException e ) {
+			throw e.getTargetException();
+		}
+	}
+
+	/**
+	 * Determines the appropriate class loader to which the generated proxy
+	 * should be scoped.
+	 *
+	 * @return The class loader appropriate for proxy construction.
+	 */
+	public static ClassLoader getProxyClassLoader() {
+		ClassLoader cl = Thread.currentThread().getContextClassLoader();
+		if ( cl == null ) {
+			cl = ResultSet.class.getClassLoader();
+		}
+		return cl;
+	}
+}
\ No newline at end of file

Modified: core/branches/Branch_3_2/src/org/hibernate/loader/Loader.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/loader/Loader.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/loader/Loader.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -48,7 +48,7 @@
 import org.hibernate.impl.FetchingScrollableResultsImpl;
 import org.hibernate.impl.ScrollableResultsImpl;
 import org.hibernate.jdbc.ColumnNameCache;
-import org.hibernate.jdbc.ResultSetWrapper;
+import org.hibernate.jdbc.ResultSetWrapperProxy;
 import org.hibernate.persister.collection.CollectionPersister;
 import org.hibernate.persister.entity.EntityPersister;
 import org.hibernate.persister.entity.Loadable;
@@ -1814,7 +1814,7 @@
 		if ( session.getFactory().getSettings().isWrapResultSetsEnabled() ) {
 			try {
 				log.debug("Wrapping result set [" + rs + "]");
-				return new ResultSetWrapper( rs, retreiveColumnNameToIndexCache( rs ) );
+				return ResultSetWrapperProxy.generateProxy( rs, retreiveColumnNameToIndexCache( rs ) );
 			}
 			catch(SQLException e) {
 				log.info("Error wrapping result set", e);

Modified: core/branches/Branch_3_2/src/org/hibernate/lob/BlobImpl.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/BlobImpl.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/BlobImpl.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -1,113 +1,34 @@
 //$Id$
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
 package org.hibernate.lob;
 
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
 import java.sql.Blob;
-import java.sql.SQLException;
 
 /**
- * A dummy implementation of <tt>java.sql.Blob</tt> that
- * may be used to insert new data into a BLOB.
  * @author Gavin King
  */
-public class BlobImpl implements Blob {
-
-	private InputStream stream;
-	private int length;
-	private boolean needsReset = false;
-
-	public BlobImpl(byte[] bytes) {
-		this.stream = new ByteArrayInputStream(bytes);
-		this.length = bytes.length;
-	}
-
-	public BlobImpl(InputStream stream, int length) {
-		this.stream = stream;
-		this.length = length;
-	}
-
-	/**
-	 * @see java.sql.Blob#length()
-	 */
-	public long length() throws SQLException {
-		return length;
-	}
-
-	/**
-	 * @see java.sql.Blob#truncate(long)
-	 */
-	public void truncate(long pos) throws SQLException {
-		excep();
-	}
-
-	/**
-	 * @see java.sql.Blob#getBytes(long, int)
-	 */
-	public byte[] getBytes(long pos, int len) throws SQLException {
-		excep(); return null;
-	}
-
-	/**
-	 * @see java.sql.Blob#setBytes(long, byte[])
-	 */
-	public int setBytes(long pos, byte[] bytes) throws SQLException {
-		excep(); return 0;
-	}
-
-	/**
-	 * @see java.sql.Blob#setBytes(long, byte[], int, int)
-	 */
-	public int setBytes(long pos, byte[] bytes, int i, int j)
-	throws SQLException {
-		excep(); return 0;
-	}
-
-	/**
-	 * @see java.sql.Blob#position(byte[], long)
-	 */
-	public long position(byte[] bytes, long pos) throws SQLException {
-		excep(); return 0;
-	}
-
-	/**
-	 * @see java.sql.Blob#getBinaryStream()
-	 */
-	public InputStream getBinaryStream() throws SQLException {
-		try {
-			if (needsReset) stream.reset();
-		}
-		catch (IOException ioe) {
-			throw new SQLException("could not reset reader");
-		}
-		needsReset = true;
-		return stream;
-	}
-
-	/**
-	 * @see java.sql.Blob#setBinaryStream(long)
-	 */
-	public OutputStream setBinaryStream(long pos) throws SQLException {
-		excep(); return null;
-	}
-
-	/**
-	 * @see java.sql.Blob#position(Blob, long)
-	 */
-	public long position(Blob blob, long pos) throws SQLException {
-		excep(); return 0;
-	}
-
-	private static void excep() {
-		throw new UnsupportedOperationException("Blob may not be manipulated from creating session");
-	}
-
-}
-
-
-
-
-
-
+public interface BlobImpl extends Blob {
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/src/org/hibernate/lob/BlobImplProxy.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/BlobImplProxy.java	                        (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/BlobImplProxy.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,148 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.lob;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.Blob;
+import java.sql.SQLException;
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+/**
+ * A proxy for a dummy implementation of <tt>java.sql.Blob</tt> that
+ * is used to insert new data into a Blob when the Connection is not used
+ * for creating new Blobs.
+ *
+ * This implementation provides minimal functionality for creating a
+ * new Blob. The only operations that are supported are {@link #length()}
+ * and {@link #getBinaryStream()}. All other operations will throw
+ * UnsupportedOperationException.
+ *
+ * The proxy extends BlobImpl so that it can be distinguished from a Blob.
+ *
+ * @author Gail Badner
+ */
+public class BlobImplProxy implements InvocationHandler {
+
+	private static final Class[] PROXY_INTERFACES = new Class[] { BlobImpl.class };
+
+	private InputStream stream;
+	private int length;
+	private boolean needsReset = false;
+
+	/**
+	 * Generates a BlobImpl proxy using byte data.
+	 *
+	 * @param bytes The data to be created as a Blob.
+	 * @return The generated proxy.
+	 */
+	public static Blob generateProxy(byte[] bytes) {
+		return ( Blob ) Proxy.newProxyInstance(
+				getProxyClassLoader(),
+				PROXY_INTERFACES,
+				new BlobImplProxy( bytes )
+		);
+	}
+
+	/**
+	 * Generates a BlobImpl proxy using a given number of bytes from an InputStream.
+	 *
+	 * @param stream The input stream of bytes to be created as a Blob.
+	 * @param length The number of bytes from stream to be written to the Blob.
+	 * @return The generated proxy.
+	 */
+	public static Blob generateProxy(InputStream stream, int length) {
+		return ( Blob ) Proxy.newProxyInstance(
+				getProxyClassLoader(),
+				PROXY_INTERFACES,
+				new BlobImplProxy( stream, length )
+		);
+	}
+
+	private BlobImplProxy(byte[] bytes) {
+		this.stream = new ByteArrayInputStream(bytes);
+		this.length = bytes.length;
+	}
+
+	private BlobImplProxy(InputStream stream, int length) {
+		this.stream = stream;
+		this.length = length;
+	}
+
+	/**
+	 * @see java.sql.Blob#length()
+	 */
+	public long length() throws SQLException {
+		return length;
+	}
+
+	/**
+	 * @see java.sql.Blob#getBinaryStream()
+	 */
+	public InputStream getBinaryStream() throws SQLException {
+		try {
+			if (needsReset) stream.reset();
+		}
+		catch ( IOException ioe) {
+			throw new SQLException("could not reset reader");
+		}
+		needsReset = true;
+		return stream;
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @throws UnsupportedOperationException if any methods other than {@link #length()}
+	 * or {@link #getBinaryStream} are invoked.
+	 */
+	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+		if ( "length".equals( method.getName() ) ) {
+			return new Long( length() );
+		}
+		if ( "getBinaryStream".equals( method.getName() ) && method.getParameterTypes().length == 0) {
+			return getBinaryStream();
+		}
+		throw new UnsupportedOperationException("Blob may not be manipulated from creating session");
+	}
+
+	/**
+	 * Determines the appropriate class loader to which the generated proxy
+	 * should be scoped.
+	 *
+	 * @return The class loader appropriate for proxy construction.
+	 */
+	public static ClassLoader getProxyClassLoader() {
+		ClassLoader cl = Thread.currentThread().getContextClassLoader();
+		if ( cl == null ) {
+			cl = BlobImpl.class.getClassLoader();
+		}
+		return cl;
+	}
+}
\ No newline at end of file

Modified: core/branches/Branch_3_2/src/org/hibernate/lob/ClobImpl.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/ClobImpl.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/ClobImpl.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -1,137 +1,34 @@
 //$Id$
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
 package org.hibernate.lob;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.Writer;
 import java.sql.Clob;
-import java.sql.SQLException;
 
 /**
- * A dummy implementation of <tt>java.sql.Clob</tt> that
- * may be used to insert new data into a CLOB.
  * @author Gavin King
  */
-public class ClobImpl implements Clob {
-
-	private Reader reader;
-	private int length;
-	private boolean needsReset = false;
-
-	public ClobImpl(String string) {
-		reader = new StringReader(string);
-		length = string.length();
-	}
-
-	public ClobImpl(Reader reader, int length) {
-		this.reader = reader;
-		this.length = length;
-	}
-
-	/**
-	 * @see java.sql.Clob#length()
-	 */
-	public long length() throws SQLException {
-		return length;
-	}
-
-	/**
-	 * @see java.sql.Clob#truncate(long)
-	 */
-	public void truncate(long pos) throws SQLException {
-		excep();
-	}
-
-	/**
-	 * @see java.sql.Clob#getAsciiStream()
-	 */
-	public InputStream getAsciiStream() throws SQLException {
-		try {
-			if (needsReset) reader.reset();
-		}
-		catch (IOException ioe) {
-			throw new SQLException("could not reset reader");
-		}
-		needsReset = true;
-		return new ReaderInputStream(reader);
-	}
-
-	/**
-	 * @see java.sql.Clob#setAsciiStream(long)
-	 */
-	public OutputStream setAsciiStream(long pos) throws SQLException {
-		excep(); return null;
-	}
-
-	/**
-	 * @see java.sql.Clob#getCharacterStream()
-	 */
-	public Reader getCharacterStream() throws SQLException {
-		try {
-			if (needsReset) reader.reset();
-		}
-		catch (IOException ioe) {
-			throw new SQLException("could not reset reader");
-		}
-		needsReset = true;
-		return reader;
-	}
-
-	/**
-	 * @see java.sql.Clob#setCharacterStream(long)
-	 */
-	public Writer setCharacterStream(long pos) throws SQLException {
-		excep(); return null;
-	}
-
-	/**
-	 * @see java.sql.Clob#getSubString(long, int)
-	 */
-	public String getSubString(long pos, int len) throws SQLException {
-		excep(); return null;
-	}
-
-	/**
-	 * @see java.sql.Clob#setString(long, String)
-	 */
-	public int setString(long pos, String string) throws SQLException {
-		excep(); return 0;
-	}
-
-	/**
-	 * @see java.sql.Clob#setString(long, String, int, int)
-	 */
-	public int setString(long pos, String string, int i, int j)
-	throws SQLException {
-		excep(); return 0;
-	}
-
-	/**
-	 * @see java.sql.Clob#position(String, long)
-	 */
-	public long position(String string, long pos) throws SQLException {
-		excep(); return 0;
-	}
-
-	/**
-	 * @see java.sql.Clob#position(Clob, long)
-	 */
-	public long position(Clob colb, long pos) throws SQLException {
-		excep(); return 0;
-	}
-
-
-	private static void excep() {
-		throw new UnsupportedOperationException("Blob may not be manipulated from creating session");
-	}
-
-}
-
-
-
-
-
-
+public interface ClobImpl extends Clob {
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/src/org/hibernate/lob/ClobImplProxy.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/ClobImplProxy.java	                        (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/ClobImplProxy.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,165 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.lob;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.SQLException;
+import java.sql.Clob;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+
+/**
+ * A proxy for a dummy implementation of <tt>java.sql.Clob</tt> that
+ * is used to insert new data into a Clob when the Connection is not used
+ * for creating new Clobs.
+ *
+ * This implementation provides minimal functionality for creating a
+ * new Clob. The only operations that are supported are {@link #length()},
+ * {@link #getAsciiStream()}, and {@link #getCharacterStream()}. All other
+ * operations will throw UnsupportedOperationException.
+ *
+ * The proxy extends ClobImpl so that it can be distinguished from a Clob.
+ *
+ *  @author Gail Badner
+ */
+public class ClobImplProxy implements InvocationHandler {
+
+	private static final Class[] PROXY_INTERFACES = new Class[] { ClobImpl.class };
+
+	private Reader reader;
+	private int length;
+	private boolean needsReset = false;
+
+	/**
+	 * Generates a BlobImpl proxy using a String.
+	 *
+	 * @param string The data to be created as a Clob.
+	 * @return The generated proxy.
+	 */
+	public static Clob generateProxy(String string) {
+		return ( Clob ) Proxy.newProxyInstance(
+				getProxyClassLoader(),
+				PROXY_INTERFACES,
+				new ClobImplProxy( string )
+		);
+	}
+
+	/**
+	 * Generates a ClobImpl proxy using a given number of characters from a Reader.
+	 *
+	 * @param reader The Reader for character data to be created as a Clob.
+	 * @param length The number of characters from Reader to be written to the Clob.
+	 * @return The generated proxy.
+	 */
+	public static Clob generateProxy(Reader reader, int length) {
+		return ( Clob ) Proxy.newProxyInstance(
+				getProxyClassLoader(),
+				PROXY_INTERFACES,
+				new ClobImplProxy( reader, length )
+		);
+	}
+
+	private ClobImplProxy(String string) {
+		reader = new StringReader(string);
+		length = string.length();
+	}
+
+	private ClobImplProxy(Reader reader, int length) {
+		this.reader = reader;
+		this.length = length;
+	}
+
+	/**
+	 * @see java.sql.Clob#length()
+	 */
+	public long length() throws SQLException {
+		return length;
+	}
+
+	/**
+	 * @see java.sql.Clob#getAsciiStream()
+	 */
+	public InputStream getAsciiStream() throws SQLException {
+		reset();
+		return new ReaderInputStream(reader);
+	}
+
+	/**
+	 * @see java.sql.Clob#getCharacterStream()
+	 */
+	public Reader getCharacterStream() throws SQLException {
+		reset();
+		return reader;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @throws UnsupportedOperationException if any methods other than {@link #length()},
+	 * {@link #getAsciiStream()}, or {@link #getCharacterStream()} are invoked.
+	 */
+	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+		if ( "length".equals( method.getName() ) ) {
+			return new Long( length() );
+		}
+		if ( "getAsciiStream".equals( method.getName() ) ) {
+			return getAsciiStream();
+		}
+		if ( "getCharacterStream".equals( method.getName() ) ) {
+			return getCharacterStream();
+		}
+		throw new UnsupportedOperationException("Clob may not be manipulated from creating session");
+	}
+
+	/**
+	 * Determines the appropriate class loader to which the generated proxy
+	 * should be scoped.
+	 *
+	 * @return The class loader appropriate for proxy construction.
+	 */
+	public static ClassLoader getProxyClassLoader() {
+		ClassLoader cl = Thread.currentThread().getContextClassLoader();
+		if ( cl == null ) {
+			cl = ClobImpl.class.getClassLoader();
+		}
+		return cl;
+	}
+
+
+	private void reset() throws SQLException {
+		try {
+			if (needsReset) reader.reset();
+		}
+		catch (IOException ioe) {
+			throw new SQLException("could not reset reader");
+		}
+		needsReset = true;
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/src/org/hibernate/lob/LobCreator.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/LobCreator.java	                        (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/LobCreator.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,96 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.lob;
+
+import java.sql.Clob;
+import java.sql.Blob;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.IOException;
+
+import org.hibernate.HibernateException;
+
+/**
+ * This interface defines the API for creating Blobs and Clobs.
+ *
+ * @author Gail Badner
+ */
+public interface LobCreator {
+
+	/**
+	 * Returns a Blob object representing a SQL BLOB created from the given array of bytes.
+	 *
+	 * @param bytes The array of bytes to be written to this BLOB object.
+	 * @return the created Blob
+	 * @throws HibernateException if the Blob could not be created
+	 */
+	Blob createBlob(byte[] bytes) throws HibernateException;
+
+	/**
+	 * Returns a Blob object representing a SQL BLOB created from the given number of bytes
+	 * from an InputStream.
+	 *
+	 * @param is The input stream of bytes to be written to this BLOB object.
+	 * @param length The number of bytes from stream to be written to this BLOB object.
+	 * @return the created Blob
+	 * @throws HibernateException if the Blob could not be created
+	 * @throws IOException if an I/O error occurs
+	 */
+	Blob createBlob(InputStream is, int length) throws HibernateException, IOException;
+
+
+	/**
+	 * Returns a Blob object representing a SQL BLOB created from the available (is.available())
+	 * number of bytes from an InputStream.
+	 *
+	 * @param is The input stream of bytes to be written to this BLOB object.
+	 * @return the created Blob
+	 * @throws HibernateException if the Blob could not be created
+	 * @throws IOException if an I/O error occurs
+	 */
+	Blob createBlob(InputStream is) throws HibernateException, IOException;
+
+	/**
+	 * Returns a Clob object representing a SQL CLOB created from the given String.
+	 *
+	 * @param string The String to be written to this CLOB object
+	 * @throws HibernateException if the Clob could not be created
+	 * @throws HibernateException
+	 */
+	Clob createClob(String string) throws HibernateException;
+
+	/**
+	 * Returns a Clob object representing a SQL CLOB created from the given number of
+	 * characters from a character stream.
+	 * 
+	 * @param reader The character stream to be written to this CLOB object.
+	 * @param length The number of characters from reader to be written to this CLOB object.
+	 * @return the created Clob
+	 * @throws HibernateException if the Clob could not be created
+	 * @throws IOException if an I/O error occurs
+	 */
+	Clob createClob(Reader reader, int length) throws HibernateException, IOException;
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorFactory.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorFactory.java	                        (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorFactory.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,75 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.lob;
+
+import org.hibernate.Session;
+import org.hibernate.AssertionFailure;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+/**
+ * A factory for creating an instance of the appropriate LobCreator implementation.
+ *
+ * @author Gail Badner
+ */
+public class LobCreatorFactory {
+
+	/**
+	 * Creates an instance of a LobCreator that does not use the Connection to create LOBs.
+	 * The returned LobCreator is appropriate for JVM and/or JDBC drivers that support JDBC3,
+	 * but not JDBC4.
+	 *
+	 * @return the LobCreator
+	 */
+	public static LobCreator createLobCreator() {
+		return new LobCreatorImplJDBC3();
+	}
+
+	/**
+	 * If the setting for Environment#USE_CONNECTION_FOR_LOB_CREATION is true, then the
+	 * returned LobCreator will use the Connection to create LOBs. If it is false, then
+	 * the returned LobCreator will not use the Connection to create LOBs.
+	 *
+	 * If the property is not set, then the returned LobCreator will use the connection to
+	 * create LOBs only if the JVM and JDBC driver support this JDBC4 functionality.
+	 *
+	 * (@see Environment#USE_CONNECTION_FOR_LOB_CREATION)
+	 *
+	 * @param session The session.
+	 * @return the LobCreator
+	 */
+	public static LobCreator createLobCreator(Session session) {
+		if ( session == null ) {
+			throw new AssertionFailure("session is null; use LobCreatorFactory.createLobCreator() instead.");
+		}
+		SessionFactoryImplementor sfi = ( SessionFactoryImplementor ) session.getSessionFactory();
+		if ( sfi.getSettings().isUseConnectionForLobCreationEnabled() ) {
+			return new LobCreatorImplJDBC4( session );
+		}
+		else {
+			return new LobCreatorImplJDBC3();
+		}
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC3.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC3.java	                        (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC3.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,79 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.lob;
+
+import java.sql.Blob;
+import java.sql.Clob;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.IOException;
+
+/**
+ * A LobCreator implementation that can be used with JVMs and JDBC drivers that support JDBC3.
+ *
+ * @author Gail Badner
+ */
+public class LobCreatorImplJDBC3 implements LobCreator {
+
+	/* package */
+	LobCreatorImplJDBC3() {
+	}
+
+	/**
+ 	 * {@inheritDoc}
+	 */
+	public Blob createBlob(byte[] bytes) {
+		return SerializableBlobProxy.generateProxy( BlobImplProxy.generateProxy( bytes ) );
+	}
+
+	/**
+ 	 * {@inheritDoc}
+	 */
+	public Blob createBlob(InputStream is, int length) {
+		return SerializableBlobProxy.generateProxy( BlobImplProxy.generateProxy( is, length ) );
+	}
+
+	/**
+ 	 * {@inheritDoc}
+	 */
+	public Blob createBlob(InputStream is) throws IOException {
+		return SerializableBlobProxy.generateProxy( BlobImplProxy.generateProxy( is, is.available() ) );
+	}
+
+	/**
+ 	 * {@inheritDoc}
+	 */
+	public Clob createClob(String string) {
+		return SerializableClobProxy.generateProxy( ClobImplProxy.generateProxy( string ) );
+	}
+
+	/**
+ 	 * {@inheritDoc}
+	 */
+	public Clob createClob(Reader reader, int length) {
+		return SerializableClobProxy.generateProxy( ClobImplProxy.generateProxy( reader, length ) );
+	}
+}

Added: core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC4.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC4.java	                        (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC4.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,195 @@
+// $Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.lob;
+
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import org.hibernate.Session;
+import org.hibernate.HibernateException;
+import org.hibernate.cfg.Environment;
+import org.hibernate.exception.JDBCExceptionHelper;
+import org.hibernate.engine.SessionImplementor;
+
+/**
+ * A LobCreator implementation that can be used with JVMs and JDBC drivers that support JDBC4. 
+ *
+ * @author Gail Badner
+ */
+public class LobCreatorImplJDBC4 implements LobCreator {
+	private final SessionImplementor session;
+
+	/* package */
+	LobCreatorImplJDBC4(Session session) {
+		this.session = ( SessionImplementor ) session;
+	}
+
+	/**
+ 	 * {@inheritDoc}
+	 */
+	public Blob createBlob(byte[] bytes) throws HibernateException {
+		Blob blob = createBlob();
+		try {
+			blob.setBytes( 1, bytes );
+		}
+		catch ( SQLException e ) {
+			throw JDBCExceptionHelper.convert(
+							session.getFactory().getSQLExceptionConverter(),
+							e,
+							"Exception invoking adding data to a Blob."
+						);
+		}
+		return blob;
+	}
+
+	/**
+ 	 * {@inheritDoc}
+	 */
+	public Blob createBlob(InputStream is, int length) throws HibernateException, IOException {
+		Blob blob = createBlob();
+		try {
+			OutputStream os = blob.setBinaryStream(1);
+			byte[] data = new byte[1];
+			for ( int i = 0; i < length && is.read( data ) != -1; i++ ) {
+				os.write( data );
+			}
+			os.flush();
+			os.close();
+			return blob;
+		}
+		catch ( SQLException e ) {
+			throw JDBCExceptionHelper.convert(
+							session.getFactory().getSQLExceptionConverter(),
+							e,
+							"Exception getting OutputStream to add data to a Blob."
+						);
+		}
+	}
+
+	/**
+ 	 * {@inheritDoc}
+	 */
+	public Blob createBlob(InputStream is) throws HibernateException, IOException {
+		return createBlob( is, is.available() );
+	}
+
+	/**
+ 	 * {@inheritDoc}
+	 */
+	public Clob createClob(String string)  throws HibernateException {
+		Clob clob = createClob();
+		try {
+			clob.setString( 1, string );
+			return clob;
+		}
+		catch ( SQLException e ) {
+			throw JDBCExceptionHelper.convert(
+				session.getFactory().getSQLExceptionConverter(),
+				e,
+				"Exception adding a String to a Clob."
+			);
+		}
+	}
+
+	/**
+ 	 * {@inheritDoc}
+	 */
+	public Clob createClob(Reader reader, int length) throws HibernateException, IOException {
+		Clob clob = createClob();
+		try {
+			Writer writer = clob.setCharacterStream( 1 );
+			char[] data = new char[1];
+			for ( int i = 0; i < length && reader.read( data ) != -1; i++ ) {
+				writer.write( data );
+			}
+			writer.flush();
+			writer.close();
+			return clob;
+		}
+		catch ( SQLException e ) {
+			throw JDBCExceptionHelper.convert(
+				session.getFactory().getSQLExceptionConverter(),
+				e,
+				"Exception getting OutputStream to add data to a Clob."
+			);
+		}
+	}
+
+	private Blob createBlob() {
+		final String CREATE_BLOB_METHOD_NAME = "createBlob";
+		return ( Blob ) invokeConnectionMethod( CREATE_BLOB_METHOD_NAME );
+	}
+
+	private Clob createClob() {
+		final String CREATE_CLOB_METHOD_NAME = "createClob";
+		return ( Clob ) invokeConnectionMethod( CREATE_CLOB_METHOD_NAME );
+	}
+
+	private Object invokeConnectionMethod(String methodName) throws HibernateException {
+		Connection connection = session.getJDBCContext().getConnectionManager().getConnection();
+		final Object emptyArray[] = { };
+		try {
+			Method method = Connection.class.getMethod( methodName, new Class[0] );
+			Object object = method.invoke( connection, emptyArray );
+			session.getJDBCContext().getConnectionManager().afterStatement();
+			return object;
+		}
+		catch ( NoSuchMethodException e ) {
+			throw new HibernateException( getMethodString( connection, methodName ) + " not supported. Set " + Environment.USE_CONNECTION_FOR_LOB_CREATION + " to false.", e );
+		}
+		catch ( AbstractMethodError e ) {
+			throw new HibernateException( "Implementation of " + getMethodString( connection, methodName ) + " not found. Set " + Environment.USE_CONNECTION_FOR_LOB_CREATION + " to false.", e );
+		}
+		catch ( InvocationTargetException e ) {
+			if ( e.getTargetException() instanceof SQLException ) {
+				throw JDBCExceptionHelper.convert(
+							session.getFactory().getSQLExceptionConverter(),
+							( SQLException ) e.getTargetException(),
+							"Exception invoking " + getMethodString( connection, methodName )
+						);
+			}
+			throw new HibernateException( "Exception invoking " + getMethodString( connection, methodName ), e.getTargetException() );
+		}
+		catch ( IllegalAccessException e ) {
+			throw new HibernateException( "Cannot access " + getMethodString( connection, methodName ), e );
+		}
+	}
+
+	private String getMethodString(Connection connection, String methodName) {
+		return new StringBuffer()
+				.append( connection.getClass().getName() )
+				.append('.')
+				.append( methodName )
+				.append( "()" ).toString();
+	}
+}

Modified: core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlob.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlob.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlob.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -1,66 +1,35 @@
 //$Id$
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
 package org.hibernate.lob;
 
-import java.io.InputStream;
-import java.io.OutputStream;
 import java.io.Serializable;
 import java.sql.Blob;
-import java.sql.SQLException;
 
 /**
  * @author Gavin King
  */
-public class SerializableBlob implements Serializable, Blob {
-	
-	private transient final Blob blob;
-	
-	public SerializableBlob(Blob blob) {
-		this.blob = blob;
-	}
-
-	public Blob getWrappedBlob() {
-		if ( blob==null ) {
-			throw new IllegalStateException("Blobs may not be accessed after serialization");
-		}
-		else {
-			return blob;
-		}
-	}
-	
-	public long length() throws SQLException {
-		return getWrappedBlob().length();
-	}
-
-	public byte[] getBytes(long pos, int length) throws SQLException {
-		return getWrappedBlob().getBytes(pos, length);
-	}
-
-	public InputStream getBinaryStream() throws SQLException {
-		return getWrappedBlob().getBinaryStream();
-	}
-
-	public long position(byte[] pattern, long start) throws SQLException {
-		return getWrappedBlob().position(pattern, start);
-	}
-
-	public long position(Blob pattern, long start) throws SQLException {
-		return getWrappedBlob().position(pattern, start);
-	}
-
-	public int setBytes(long pos, byte[] bytes) throws SQLException {
-		return getWrappedBlob().setBytes(pos, bytes);
-	}
-
-	public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException {
-		return getWrappedBlob().setBytes(pos, bytes, offset, len);
-	}
-
-	public OutputStream setBinaryStream(long pos) throws SQLException {
-		return getWrappedBlob().setBinaryStream(pos);
-	}
-
-	public void truncate(long len) throws SQLException {
-		getWrappedBlob().truncate(len);
-	}
-
-}
+public interface SerializableBlob extends Serializable, Blob {
+	public Blob getWrappedBlob();
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlobProxy.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlobProxy.java	                        (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlobProxy.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,104 @@
+// $Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.lob;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.InvocationTargetException;
+import java.sql.Blob;
+import org.hibernate.HibernateException;
+
+/**
+ * A proxy for SerializableBlob objects which delegates all Blob methods to
+ * a wrapped Blob.
+ *
+ * @author Gail Badner
+ */
+public class SerializableBlobProxy implements InvocationHandler {
+
+	private static final Class[] PROXY_INTERFACES = new Class[] { SerializableBlob.class };
+
+	private transient final Blob blob;
+
+	/**
+	 * Generates a SerializableBlob proxy wrapping the provided Blob object.
+	 *
+	 * @param blob The Blob to wrap.
+	 * @return The generated proxy.
+	 */
+	public static Blob generateProxy(Blob blob) {
+		return ( Blob ) Proxy.newProxyInstance(
+				getProxyClassLoader(),
+		        PROXY_INTERFACES,
+		         new SerializableBlobProxy( blob )
+		);
+	}
+
+	private SerializableBlobProxy(Blob blob) {
+		this.blob = blob;
+	}
+
+	public Blob getWrappedBlob() {
+		if ( blob == null ) {
+			throw new IllegalStateException( "Blobs may not be accessed after serialization" );
+		}
+		else {
+			return blob;
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+		if ( "getWrappedBlob".equals( method.getName() ) ) {
+			return getWrappedBlob();
+		}
+		try {
+			return method.invoke( getWrappedBlob(), args );
+		}
+		catch( AbstractMethodError e ) {
+			throw new HibernateException("The JDBC driver does not implement the method: " + method, e);
+		}
+		catch (InvocationTargetException e ) {
+			throw e.getTargetException();	
+		}
+	}
+
+	/**
+	 * Determines the appropriate class loader to which the generated proxy
+	 * should be scoped.
+	 *
+	 * @return The class loader appropriate for proxy construction.
+	 */
+	public static ClassLoader getProxyClassLoader() {
+		ClassLoader cl = Thread.currentThread().getContextClassLoader();
+		if ( cl == null ) {
+			cl = SerializableBlob.class.getClassLoader();
+		}
+		return cl;
+	}
+}

Modified: core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClob.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClob.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClob.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -1,76 +1,36 @@
 //$Id$
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
 package org.hibernate.lob;
 
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
 import java.io.Serializable;
-import java.io.Writer;
 import java.sql.Clob;
-import java.sql.SQLException;
 
 /**
  * @author Gavin King
  */
-public class SerializableClob implements Serializable, Clob {
+public interface SerializableClob extends Serializable, Clob {
 
-	private transient final Clob clob;
-	
-	public SerializableClob(Clob blob) {
-		this.clob = blob;
-	}
-
-	public Clob getWrappedClob() {
-		if ( clob==null ) {
-			throw new IllegalStateException("Clobs may not be accessed after serialization");
-		}
-		else {
-			return clob;
-		}
-	}
-	
-	public long length() throws SQLException {
-		return getWrappedClob().length();
-	}
-
-	public String getSubString(long pos, int length) throws SQLException {
-		return getWrappedClob().getSubString(pos, length);
-	}
-
-	public Reader getCharacterStream() throws SQLException {
-		return getWrappedClob().getCharacterStream();
-	}
-
-	public InputStream getAsciiStream() throws SQLException {
-		return getWrappedClob().getAsciiStream();
-	}
-
-	public long position(String searchstr, long start) throws SQLException {
-		return getWrappedClob().position(searchstr, start);
-	}
-
-	public long position(Clob searchstr, long start) throws SQLException {
-		return getWrappedClob().position(searchstr, start);
-	}
-
-	public int setString(long pos, String str) throws SQLException {
-		return getWrappedClob().setString(pos, str);
-	}
-
-	public int setString(long pos, String str, int offset, int len) throws SQLException {
-		return getWrappedClob().setString(pos, str, offset, len);
-	}
-
-	public OutputStream setAsciiStream(long pos) throws SQLException {
-		return getWrappedClob().setAsciiStream(pos);
-	}
-
-	public Writer setCharacterStream(long pos) throws SQLException {
-		return getWrappedClob().setCharacterStream(pos);
-	}
-
-	public void truncate(long len) throws SQLException {
-		getWrappedClob().truncate(len);
-	}
-
+	public Clob getWrappedClob();
 }

Added: core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClobProxy.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClobProxy.java	                        (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClobProxy.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,105 @@
+// $Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.lob;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.Clob;
+
+import org.hibernate.HibernateException;
+
+/**
+ * A proxy for SerializableClob objects which delegates all Clob methods to
+ * a wrapped Clob.
+ *
+ * @author Gail Badner
+ */
+public class SerializableClobProxy implements InvocationHandler {
+
+	private static final Class[] PROXY_INTERFACES = new Class[] { SerializableClob.class };
+
+	private transient final Clob clob;
+
+	/**
+	 * Generates a SerializableClob proxy wrapping the provided Clob object.
+	 *
+	 * @param clob The Clob to wrap.
+	 * @return The generated proxy.
+	 */
+	public static Clob generateProxy(Clob clob) {
+		return ( Clob ) Proxy.newProxyInstance(
+				getProxyClassLoader(),
+		        PROXY_INTERFACES,
+		         new SerializableClobProxy( clob )
+		);
+	}
+
+	private SerializableClobProxy(Clob clob) {
+		this.clob = clob;
+	}
+
+	public Clob getWrappedClob() {
+		if ( clob==null ) {
+			throw new IllegalStateException("Clobs may not be accessed after serialization");
+		}
+		else {
+			return clob;
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+		if ( "getWrappedClob".equals( method.getName() ) ) {
+			return getWrappedClob();
+		}
+		try {
+			return method.invoke( getWrappedClob(), args );
+		}
+		catch( AbstractMethodError e ) {
+			throw new HibernateException("The JDBC driver does not implement the method: " + method, e);
+		}
+		catch( InvocationTargetException e ) {
+			throw e.getTargetException();
+		}
+	}
+
+	/**
+	 * Determines the appropriate class loader to which the generated proxy
+	 * should be scoped.
+	 *
+	 * @return The class loader appropriate for proxy construction.
+	 */
+	public static ClassLoader getProxyClassLoader() {
+		ClassLoader cl = Thread.currentThread().getContextClassLoader();
+		if ( cl == null ) {
+			cl = Clob.class.getClassLoader();
+		}
+		return cl;
+	}
+}

Modified: core/branches/Branch_3_2/src/org/hibernate/type/BlobType.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/type/BlobType.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/type/BlobType.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -1,4 +1,28 @@
 //$Id$
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
 package org.hibernate.type;
 
 import java.io.Serializable;
@@ -18,6 +42,7 @@
 import org.hibernate.engine.SessionImplementor;
 import org.hibernate.lob.BlobImpl;
 import org.hibernate.lob.SerializableBlob;
+import org.hibernate.lob.SerializableBlobProxy;
 import org.hibernate.util.ArrayHelper;
 
 /**
@@ -55,7 +80,7 @@
 
 	public Object get(ResultSet rs, String name) throws HibernateException, SQLException {
 		Blob value = rs.getBlob(name);
-		return rs.wasNull() ? null : new SerializableBlob(value);
+		return rs.wasNull() ? null : SerializableBlobProxy.generateProxy(value);
 	}
 
 	public Class getReturnedClass() {

Modified: core/branches/Branch_3_2/src/org/hibernate/type/ClobType.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/type/ClobType.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/type/ClobType.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -1,4 +1,28 @@
 //$Id$
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
 package org.hibernate.type;
 
 import java.io.Serializable;
@@ -19,6 +43,7 @@
 import org.hibernate.engine.SessionImplementor;
 import org.hibernate.lob.ClobImpl;
 import org.hibernate.lob.SerializableClob;
+import org.hibernate.lob.SerializableClobProxy;
 import org.hibernate.util.ArrayHelper;
 
 /**
@@ -56,7 +81,7 @@
 
 	public Object get(ResultSet rs, String name) throws HibernateException, SQLException {
 		Clob value = rs.getClob(name);
-		return rs.wasNull() ? null : new SerializableClob(value);
+		return rs.wasNull() ? null : SerializableClobProxy.generateProxy(value);
 	}
 
 	public Class getReturnedClass() {

Modified: core/branches/Branch_3_2/test/org/hibernate/test/AllTests.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/AllTests.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/test/org/hibernate/test/AllTests.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -146,7 +146,17 @@
 import org.hibernate.test.legacy.SQLLoaderTest;
 import org.hibernate.test.legacy.StatisticsTest;
 import org.hibernate.test.lob.BlobTest;
+import org.hibernate.test.lob.BlobFromLobCreatorDefaultTest;
+import org.hibernate.test.lob.BlobFromLobCreatorJDBC3ConnRelOnCloseTest;
+import org.hibernate.test.lob.BlobFromLobCreatorJDBC3Test;
+import org.hibernate.test.lob.BlobFromLobCreatorJDBC4ConnRelOnCloseTest;
+import org.hibernate.test.lob.BlobFromLobCreatorJDBC4Test;
 import org.hibernate.test.lob.ClobTest;
+import org.hibernate.test.lob.ClobFromLobCreatorDefaultTest;
+import org.hibernate.test.lob.ClobFromLobCreatorJDBC3ConnRelOnCloseTest;
+import org.hibernate.test.lob.ClobFromLobCreatorJDBC3Test;
+import org.hibernate.test.lob.ClobFromLobCreatorJDBC4ConnRelOnCloseTest;
+import org.hibernate.test.lob.ClobFromLobCreatorJDBC4Test;
 import org.hibernate.test.lob.SerializableTypeTest;
 import org.hibernate.test.manytomany.ManyToManyTest;
 import org.hibernate.test.manytomanyassociationclass.compositeid.ManyToManyAssociationClassCompositeIdTest;
@@ -471,7 +481,17 @@
 			suite.addTest( AnyTypeTest.suite() );
 			suite.addTest( SerializableTypeTest.suite() );
 			suite.addTest( BlobTest.suite() );
+			suite.addTest( BlobFromLobCreatorDefaultTest.suite() );
+			suite.addTest( BlobFromLobCreatorJDBC3ConnRelOnCloseTest.suite() );
+			suite.addTest( BlobFromLobCreatorJDBC3Test.suite() );
+			suite.addTest( BlobFromLobCreatorJDBC4ConnRelOnCloseTest.suite() );
+			suite.addTest( BlobFromLobCreatorJDBC4Test.suite() );
 			suite.addTest( ClobTest.suite() );
+			suite.addTest( ClobFromLobCreatorDefaultTest.suite() );
+			suite.addTest( ClobFromLobCreatorJDBC3ConnRelOnCloseTest.suite() );
+			suite.addTest( ClobFromLobCreatorJDBC3Test.suite() );
+			suite.addTest( ClobFromLobCreatorJDBC4ConnRelOnCloseTest.suite() );
+			suite.addTest( ClobFromLobCreatorJDBC4Test.suite() );
 			suite.addTest( IdentifierPropertyReferencesTest.suite() );
 			suite.addTest( DeleteTransientEntityTest.suite() );
 			suite.addTest( UserCollectionTypeTest.suite() );
@@ -629,4 +649,4 @@
 			}
 		}
 	}
-}
\ No newline at end of file
+}

Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobFromLobCreatorTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobFromLobCreatorTest.java	                        (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobFromLobCreatorTest.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,161 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.lob;
+
+import java.sql.Blob;
+import java.sql.SQLException;
+import java.sql.Connection;
+import java.io.IOException;
+import java.io.ByteArrayInputStream;
+
+import org.hibernate.Hibernate;
+import org.hibernate.Session;
+import org.hibernate.AssertionFailure;
+import org.hibernate.HibernateException;
+import org.hibernate.SessionException;
+import org.hibernate.lob.LobCreator;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.dialect.Dialect;
+
+/**
+ * This class extends AbstractBlobTest to provide additional tests when
+ * using a LobCreator to create LOB locators.
+ *
+ * @author Gail Badner
+ */
+public abstract class AbstractBlobFromLobCreatorTest extends AbstractBlobTest {
+
+	public AbstractBlobFromLobCreatorTest(String name) {
+		super( name );
+	}
+
+	public void configure(Configuration cfg) {
+		super.configure( cfg );
+		if ( getUseConnectionForLobCreationPropertyValue() == null ) {
+			cfg.setProperty( Environment.USE_CONNECTION_FOR_LOB_CREATION, "" );
+		}
+		else {
+			cfg.setProperty(
+					Environment.USE_CONNECTION_FOR_LOB_CREATION,
+					String.valueOf( getUseConnectionForLobCreationPropertyValue().booleanValue() )
+			);
+		}
+	}
+
+	public boolean appliesTo(Dialect dialect) {
+		if ( ! dialect.supportsExpectedLobUsagePattern() ) {
+			reportSkip( "database/driver does not support expected LOB usage pattern", "LOB support" );
+			return false;
+		}
+		return true;
+	}
+
+	protected abstract Boolean getUseConnectionForLobCreationPropertyValue();
+
+	protected Blob createBlobLocator(Session s, byte[] bytes) {
+		return Hibernate.getLobCreator( s ).createBlob( bytes );
+	}
+
+	protected Blob createBlobLocatorFromStream(Session s, byte[] bytes) throws IOException {
+		return Hibernate.getLobCreator( s ).createBlob( new ByteArrayInputStream( bytes ) );
+	}
+
+	protected Blob createBlobLocatorFromStreamUsingLength(Session s, byte[] bytes) throws IOException {
+		return Hibernate.getLobCreator( s ).createBlob( new ByteArrayInputStream( bytes ), bytes.length );
+	}
+
+	protected abstract Class getExpectedLobCreatorClass() throws SQLException ;
+
+	public void testUseConnectionForLobCreationEnabledSetting() throws SQLException {
+		Boolean propVal = getUseConnectionForLobCreationPropertyValue();
+		if ( propVal == null ) {
+			if ( jvmAndDriverSupportUseConnectionForLobCreation() != isUseConnectionForLobCreationEnabled() ) {
+				throw new AssertionFailure( "JVM and JDBC driver support is inconsistent with setting for using Connection to create LOBs." );
+
+			}
+		}
+		else {
+			if ( propVal.booleanValue() != isUseConnectionForLobCreationEnabled() ) {
+				throw new AssertionFailure( "Non-null Environment.USE_CONNECTION_FOR_LOB_CREATION value is inconstent with setting." );
+			}
+		}
+	}
+
+	public void testCorrectLobCreator() throws Exception {
+		Session s = openSession();
+		LobCreator lobCreator = Hibernate.getLobCreator( s );
+		assertEquals( getExpectedLobCreatorClass(), lobCreator.getClass() );
+		s.close();
+	}
+
+	public void testGetLobCreatorWithNullSession() {
+		try {
+			Hibernate.getLobCreator( null );
+			fail( "should have failed with null session" );
+		}
+		catch ( AssertionFailure ex ) {
+			// expected
+		}
+	}
+
+	public void testCreateBlobLocatorAfterSessionClose() throws Throwable {
+		Session s = openSession();
+		s.close();
+		byte[] bytes = buildRecursively( BLOB_SIZE, true );
+		try {
+			createBlobLocator( s, bytes );
+			if ( isUseConnectionForLobCreationEnabled() ) {
+				fail( "should have failed w/ SessionException" );
+			}
+		}
+		catch ( SessionException e ) {
+			if ( ! isUseConnectionForLobCreationEnabled() ) {
+				fail( "should not have failed w/ SessionException" );
+			}
+		}
+	}
+
+	protected boolean isUseConnectionForLobCreationEnabled() {
+		return ( ( SessionFactoryImplementor ) getSessions() ).getSettings().isUseConnectionForLobCreationEnabled();
+	}
+
+	protected boolean jvmAndDriverSupportUseConnectionForLobCreation() throws SQLException {
+		if ( ! Environment.jvmSupportsJDBC4() ) {
+			return false;
+		}
+		Class c = ( ( SessionFactoryImplementor ) getSessions() ).getConnectionProvider().getConnection().getClass();
+		try {
+			return !( Connection.class.equals( c.getMethod( "createBlob", new Class[0] ).getDeclaringClass() ) ||
+					Connection.class.equals( c.getMethod( "createClob", new Class[0] ).getDeclaringClass() ) );
+		}
+		catch ( NoSuchMethodException e ) {
+			return false;
+		}
+	}
+
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobTest.java	                        (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobTest.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,490 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.lob;
+
+import java.sql.Blob;
+import java.sql.SQLException;
+import java.io.IOException;
+
+import junit.framework.AssertionFailedError;
+
+import org.hibernate.LockMode;
+import org.hibernate.Session;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
+import org.hibernate.util.ArrayHelper;
+
+/**
+ * Test various access scenarios for eager and lazy materialization
+ * of BLOB data, as well as bounded and unbounded materialization
+ * and mutation.
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractBlobTest extends DatabaseSpecificFunctionalTestCase {
+	public static final int BLOB_SIZE = 10000;
+
+	public AbstractBlobTest(String name) {
+		super( name );
+	}
+
+	public String[] getMappings() {
+		return new String[] { "lob/LobMappings.hbm.xml" };
+	}
+
+	public boolean appliesTo(Dialect dialect) {
+		if ( ! dialect.supportsExpectedLobUsagePattern() ) {
+			reportSkip( "database/driver does not support expected LOB usage pattern", "LOB support" );
+			return false;
+		}
+		return true;
+	}
+
+	protected abstract Blob createBlobLocator(Session s, byte[] bytes);
+
+	protected abstract Blob createBlobLocatorFromStream(Session s, byte[] bytes) throws IOException;
+
+	protected abstract Blob createBlobLocatorFromStreamUsingLength(Session s, byte[] bytes) throws IOException ;
+
+	protected boolean skipLobLocatorTests()  throws SQLException {
+		return false;
+	}
+
+	public void configure(Configuration cfg) {
+		super.configure( cfg );
+		// set connection pool size to 0 so that tests will always use a clean connection;
+		// this ensures that the test does not use LOB data left on the connection from
+		// prior to being returned to the connection pool.
+		cfg.setProperty( Environment.POOL_SIZE, "0" );
+		// ConnectionReleaseMode.AFTER_TRANSACTION is the default for non-JTA connection.
+		// The Connection used for the unit tests is non-JTA. This setting for
+		// Environment.RELEASE_CONNECTIONS is just to make it explicit for these tests.
+		cfg.setProperty( Environment.RELEASE_CONNECTIONS, "after_transaction" );
+	}
+
+	public void testBoundedMaterializedBlobAccess() {
+		byte[] original = buildRecursively( BLOB_SIZE, true );
+		byte[] changed = buildRecursively( BLOB_SIZE, false );
+
+		Session s = openSession();
+		s.beginTransaction();
+		LobHolder entity = new LobHolder();
+		entity.setMaterializedBlob( original );
+		s.save( entity );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		assertEquals( BLOB_SIZE, entity.getMaterializedBlob().length );
+		assertEquals( original, entity.getMaterializedBlob() );
+		entity.setMaterializedBlob( changed );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		assertEquals( BLOB_SIZE, entity.getMaterializedBlob().length );
+		assertEquals( changed, entity.getMaterializedBlob() );
+		s.delete( entity );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testBoundedBlobLocatorAccess() throws Throwable {
+		if ( skipLobLocatorTests() ) {
+			return;
+		}
+
+		byte[] original = buildRecursively( BLOB_SIZE, true );
+		byte[] changed = buildRecursively( BLOB_SIZE, false );
+
+		Session s = openSession();
+		s.beginTransaction();
+		LobHolder entity = new LobHolder();
+		entity.setBlobLocator( createBlobLocator( s, original ) );
+		s.save( entity );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+		assertEquals( original, extractData( entity.getBlobLocator() ) );
+		s.getTransaction().commit();
+		s.close();
+
+		// test mutation via setting the new blob data...
+		if ( supportsLobValueChangePropogation() ) {
+			s = openSession();
+			s.beginTransaction();
+			entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+			entity.getBlobLocator().truncate( 1 );
+			entity.getBlobLocator().setBytes( 1, changed );
+			s.getTransaction().commit();
+			s.close();
+
+			s = openSession();
+			s.beginTransaction();
+			entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+			assertNotNull( entity.getBlobLocator() );
+			assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+			assertEquals( changed, extractData( entity.getBlobLocator() ) );
+			entity.getBlobLocator().truncate( 1 );
+			entity.getBlobLocator().setBytes( 1, original );
+			s.getTransaction().commit();
+			s.close();
+		}
+
+		// test mutation via supplying a new blob locator instance...
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+		assertNotNull( entity.getBlobLocator() );
+		assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+		assertEquals( original, extractData( entity.getBlobLocator() ) );
+		entity.setBlobLocator( createBlobLocator( s, changed ) );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+		assertEquals( changed, extractData( entity.getBlobLocator() ) );
+		s.delete( entity );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testBoundedBlobLocatorAccessFromStream() throws Throwable {
+		if ( skipLobLocatorTests() ) {
+			return;
+		}
+
+		byte[] original = buildRecursively( BLOB_SIZE, true );
+		byte[] changed = buildRecursively( BLOB_SIZE, false );
+
+		Session s = openSession();
+		s.beginTransaction();
+		LobHolder entity = new LobHolder();
+		entity.setBlobLocator( createBlobLocatorFromStream( s, original ) );
+		s.save( entity );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+		assertEquals( original, extractData( entity.getBlobLocator() ) );
+		s.getTransaction().commit();
+		s.close();
+
+		// test mutation via setting the new blob data...
+		if ( supportsLobValueChangePropogation() ) {
+			s = openSession();
+			s.beginTransaction();
+			entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+			entity.getBlobLocator().truncate( 1 );
+			entity.getBlobLocator().setBytes( 1, changed );
+			s.getTransaction().commit();
+			s.close();
+
+			s = openSession();
+			s.beginTransaction();
+			entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+			assertNotNull( entity.getBlobLocator() );
+			assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+			assertEquals( changed, extractData( entity.getBlobLocator() ) );
+			entity.getBlobLocator().truncate( 1 );
+			entity.getBlobLocator().setBytes( 1, original );
+			s.getTransaction().commit();
+			s.close();
+		}
+
+		// test mutation via supplying a new blob locator instance...
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+		assertNotNull( entity.getBlobLocator() );
+		assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+		assertEquals( original, extractData( entity.getBlobLocator() ) );
+		entity.setBlobLocator( createBlobLocatorFromStream( s, changed ) );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+		assertEquals( changed, extractData( entity.getBlobLocator() ) );
+		s.delete( entity );
+		s.getTransaction().commit();
+		s.close();
+
+	}
+
+	public void testBoundedBlobLocatorAccessFromStreamUsingLength() throws Throwable {
+		if ( skipLobLocatorTests() ) {
+			return;
+		}
+
+		byte[] original = buildRecursively( BLOB_SIZE, true );
+		byte[] changed = buildRecursively( BLOB_SIZE, false );
+
+		Session s = openSession();
+		s.beginTransaction();
+		LobHolder entity = new LobHolder();
+		entity.setBlobLocator( createBlobLocatorFromStreamUsingLength( s, original ) );
+		s.save( entity );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+		assertEquals( original, extractData( entity.getBlobLocator() ) );
+		s.getTransaction().commit();
+		s.close();
+
+		// test mutation via setting the new blob data...
+		if ( supportsLobValueChangePropogation() ) {
+			s = openSession();
+			s.beginTransaction();
+			entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+			entity.getBlobLocator().truncate( 1 );
+			entity.getBlobLocator().setBytes( 1, changed );
+			s.getTransaction().commit();
+			s.close();
+
+			s = openSession();
+			s.beginTransaction();
+			entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+			assertNotNull( entity.getBlobLocator() );
+			assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+			assertEquals( changed, extractData( entity.getBlobLocator() ) );
+			entity.getBlobLocator().truncate( 1 );
+			entity.getBlobLocator().setBytes( 1, original );
+			s.getTransaction().commit();
+			s.close();
+		}
+
+		// test mutation via supplying a new blob locator instance...
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+		assertNotNull( entity.getBlobLocator() );
+		assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+		assertEquals( original, extractData( entity.getBlobLocator() ) );
+		entity.setBlobLocator( createBlobLocatorFromStreamUsingLength( s, changed ) );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+		assertEquals( changed, extractData( entity.getBlobLocator() ) );
+		s.delete( entity );
+		s.getTransaction().commit();
+		s.close();
+
+	}
+
+	public void testUnboundedBlobLocatorAccess() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+
+		// Note: unbounded mutation of the underlying lob data is completely
+		// unsupported; most databases would not allow such a construct anyway.
+		// Thus here we are only testing materialization...
+
+		byte[] original = buildRecursively( BLOB_SIZE, true );
+
+		Session s = openSession();
+		s.beginTransaction();
+		LobHolder entity = new LobHolder();
+		entity.setBlobLocator( createBlobLocator( s, original ) );
+		s.save( entity );
+		s.getTransaction().commit();
+		s.close();
+
+		// load the entity with the blob locator, and close the session/transaction;
+		// at that point it is unbounded...
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		s.getTransaction().commit();
+		s.close();
+
+		assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+		assertEquals( original, extractData( entity.getBlobLocator() ) );
+
+		s = openSession();
+		s.beginTransaction();
+		s.delete( entity );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testCreateAndAccessLobLocatorInSessionNoTransaction() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+		Session s = openSession();
+		byte[] bytes = buildRecursively( BLOB_SIZE, true );
+		Blob blob = createBlobLocator( s, bytes );
+		assertEquals( BLOB_SIZE, blob.length() );
+		assertEquals( bytes, extractData( blob ) );
+		s.close();
+	}
+
+	public void testCreateAndAccessLobLocatorInTransaction() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+		Session s = openSession();
+		s.getTransaction().begin();
+		byte bytes[] = buildRecursively( BLOB_SIZE, true );
+		Blob blob = createBlobLocator( s, bytes );
+		assertEquals( BLOB_SIZE, blob.length() );
+		assertEquals( bytes, extractData( blob ) );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testCreateLobLocatorInTransactionAccessOutOfTransaction() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+		Session s = openSession();
+		s.getTransaction().begin();
+		byte bytes[] = buildRecursively( BLOB_SIZE, true );
+		Blob blob = createBlobLocator( s, bytes );
+		s.getTransaction().commit();
+		assertEquals( BLOB_SIZE, blob.length() );
+		assertEquals( bytes, extractData( blob ) );
+		s.close();
+	}
+
+	public void testCreateLobLocatorInTransactionAccessInNextTransaction() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+		Session s = openSession();
+		s.getTransaction().begin();
+		byte bytes[] = buildRecursively( BLOB_SIZE, true );
+		Blob blob = createBlobLocator( s, bytes );
+		s.getTransaction().commit();
+		s.getTransaction().begin();
+		assertEquals( BLOB_SIZE, blob.length() );
+		assertEquals( bytes, extractData( blob ) );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testCreateLobLocatorInTransactionAccessAfterSessionClose() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+		Session s = openSession();
+		s.getTransaction().begin();
+		byte bytes[] = buildRecursively( BLOB_SIZE, true );
+		Blob blob = createBlobLocator( s, bytes );
+		s.getTransaction().commit();
+		s.close();
+		assertEquals( BLOB_SIZE, blob.length() );
+		assertEquals( bytes, extractData( blob ) );
+	}
+
+	public void testCreateLobLocatorInTransactionAccessInNextSession() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+		Session s = openSession();
+		s.getTransaction().begin();
+		byte bytes[] = buildRecursively( BLOB_SIZE, true );
+		Blob blob = createBlobLocator( s, bytes );
+		s.getTransaction().commit();
+		s.close();
+		s = openSession();
+		assertEquals( BLOB_SIZE, blob.length() );
+		assertEquals( bytes, extractData( blob ) );
+		s.close();
+	}
+
+	public void testCreateLobLocatorInTransactionAccessInNextSessionTransaction() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+		Session s = openSession();
+		s.getTransaction().begin();
+		byte bytes[] = buildRecursively( BLOB_SIZE, true );
+		Blob blob = createBlobLocator( s, bytes );
+		s.getTransaction().commit();
+		s.close();
+		s = openSession();
+		s.getTransaction().begin();
+		assertEquals( BLOB_SIZE, blob.length() );
+		assertEquals( bytes, extractData( blob ) );
+		s.getTransaction().commit();
+		s.close();
+	}
+	
+	protected byte[] extractData(Blob blob) throws Throwable {
+		byte bytesRead[] = new byte[ ( int ) blob.length() ];
+		blob.getBinaryStream().read( bytesRead );
+		return bytesRead;
+	}
+
+	protected byte[] buildRecursively(int size, boolean on) {
+		byte[] data = new byte[size];
+		data[0] = mask( on );
+		for ( int i = 0; i < size; i++ ) {
+			data[i] = mask( on );
+			on = !on;
+		}
+		return data;
+	}
+
+	private byte mask(boolean on) {
+		return on ? ( byte ) 1 : ( byte ) 0;
+	}
+
+	public static void assertEquals(byte[] val1, byte[] val2) {
+		if ( !ArrayHelper.isEquals( val1, val2 ) ) {
+			throw new AssertionFailedError( "byte arrays did not match" );
+		}
+	}
+}

Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobFromLobCreatorTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobFromLobCreatorTest.java	                        (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobFromLobCreatorTest.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,156 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.lob;
+
+import java.sql.SQLException;
+import java.sql.Connection;
+import java.sql.Clob;
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.hibernate.Hibernate;
+import org.hibernate.Session;
+import org.hibernate.AssertionFailure;
+import org.hibernate.SessionException;
+import org.hibernate.lob.LobCreator;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.dialect.Dialect;
+
+/**
+ * This class extends AbstractClobTest to provide additional tests when
+ * using a LobCreator to create LOB locators.
+ *
+ * @author Gail Badner
+ */
+public abstract class AbstractClobFromLobCreatorTest extends AbstractClobTest {
+
+	public AbstractClobFromLobCreatorTest(String name) {
+		super( name );
+	}
+
+	public void configure(Configuration cfg) {
+		super.configure( cfg );
+		if ( getUseConnectionForLobCreationPropertyValue() == null ) {
+			cfg.setProperty( Environment.USE_CONNECTION_FOR_LOB_CREATION, "" );
+		}
+		else {
+			cfg.setProperty(
+					Environment.USE_CONNECTION_FOR_LOB_CREATION,
+					String.valueOf( getUseConnectionForLobCreationPropertyValue().booleanValue() )
+			);
+		}
+	}
+
+	public boolean appliesTo(Dialect dialect) {
+		if ( ! dialect.supportsExpectedLobUsagePattern() ) {
+			reportSkip( "database/driver does not support expected LOB usage pattern", "LOB support" );
+			return false;
+		}
+		return true;
+	}
+
+	protected abstract Boolean getUseConnectionForLobCreationPropertyValue();
+
+	protected Clob createClobLocator(Session s, String str) {
+		return Hibernate.getLobCreator( s ).createClob( str );
+	}
+
+	protected Clob createClobLocatorFromStreamUsingLength(Session s, String str) throws IOException {
+		return Hibernate.getLobCreator( s ).createClob( new StringReader( str ), str.length() );
+	}
+
+	protected abstract Class getExpectedLobCreatorClass() throws SQLException ;
+
+	public void testUseConnectionForLobCreationEnabledSetting() throws SQLException {
+		Boolean propVal = getUseConnectionForLobCreationPropertyValue();
+		if ( propVal == null ) {
+			if ( jvmAndDriverSupportUseConnectionForLobCreation() != isUseConnectionForLobCreationEnabled() ) {
+				throw new AssertionFailure( "JVM and JDBC driver support is inconsistent with setting for using Connection to create LOBs." );
+
+			}
+		}
+		else {
+			if ( propVal.booleanValue() != isUseConnectionForLobCreationEnabled() ) {
+				throw new AssertionFailure( "Non-null Environment.USE_CONNECTION_FOR_LOB_CREATION value is inconstent with setting." );
+			}
+		}
+	}
+
+	public void testCorrectLobCreator() throws Exception {
+		Session s = openSession();
+		LobCreator lobCreator = Hibernate.getLobCreator( s );
+		assertEquals( getExpectedLobCreatorClass(), lobCreator.getClass() );
+		s.close();
+	}
+
+	public void testGetLobCreatorWithNullSession() {
+		try {
+			Hibernate.getLobCreator( null );
+			fail( "should have failed with null session" );
+		}
+		catch ( AssertionFailure ex ) {
+			// expected
+		}
+	}
+
+	public void testCreateClobLocatorAfterSessionClose() throws Throwable {
+		Session s = openSession();
+		s.close();
+		String str = buildRecursively( CLOB_SIZE, 'x');
+		try {
+			createClobLocator( s, str );
+			if ( isUseConnectionForLobCreationEnabled() ) {
+				fail( "should have failed w/ SessionException" );
+			}
+		}
+		catch ( SessionException e ) {
+			if ( ! isUseConnectionForLobCreationEnabled() ) {
+				fail( "should not have failed w/ SessionException" );
+			}
+		}
+	}
+
+	protected boolean isUseConnectionForLobCreationEnabled() {
+		return ( ( SessionFactoryImplementor ) getSessions() ).getSettings().isUseConnectionForLobCreationEnabled();
+	}
+
+	protected boolean jvmAndDriverSupportUseConnectionForLobCreation() throws SQLException {
+		if ( ! Environment.jvmSupportsJDBC4() ) {
+			return false;
+		}
+		Class c = ( ( SessionFactoryImplementor ) getSessions() ).getConnectionProvider().getConnection().getClass();
+		try {
+			return !( Connection.class.equals( c.getMethod( "createBlob", new Class[0] ).getDeclaringClass() ) ||
+					Connection.class.equals( c.getMethod( "createClob", new Class[0] ).getDeclaringClass() ) );
+		}
+		catch ( NoSuchMethodException e ) {
+			return false;
+		}
+	}
+
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobTest.java	                        (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobTest.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,410 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.lob;
+
+import java.sql.SQLException;
+import java.sql.Clob;
+import java.io.IOException;
+
+import org.hibernate.LockMode;
+import org.hibernate.Session;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.dialect.H2Dialect;
+import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
+
+/**
+ * Test various access scenarios for eager and lazy materialization
+ * of CLOB data, as well as bounded and unbounded materialization
+ * and mutation.
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractClobTest extends DatabaseSpecificFunctionalTestCase {
+	public static final int CLOB_SIZE = 10000;
+
+	public AbstractClobTest(String name) {
+		super( name );
+	}
+
+	public String[] getMappings() {
+		return new String[] { "lob/LobMappings.hbm.xml" };
+	}
+
+	public boolean appliesTo(Dialect dialect) {
+		if ( ! dialect.supportsExpectedLobUsagePattern() ) {
+			reportSkip( "database/driver does not support expected LOB usage pattern", "LOB support" );
+			return false;
+		}
+		return true;
+	}
+
+	protected abstract Clob createClobLocator(Session s, String str);
+
+	protected abstract Clob createClobLocatorFromStreamUsingLength(Session s, String str ) throws IOException ;
+
+	protected boolean skipLobLocatorTests()  throws SQLException {
+		return false;
+	}
+
+	public void configure(Configuration cfg) {
+		super.configure( cfg );
+		// set connection pool size to 0 so that tests will always use a clean connection;
+		// this ensures that the test does not use LOB data left on the connection from
+		// prior to being returned to the connection pool.
+		cfg.setProperty( Environment.POOL_SIZE, "0" );
+		// ConnectionReleaseMode.AFTER_TRANSACTION is the default for non-JTA connection.
+		// The Connection used for the unit tests is non-JTA. This setting for
+		// Environment.RELEASE_CONNECTIONS is just to make it explicit for these tests.
+		cfg.setProperty( Environment.RELEASE_CONNECTIONS, "after_transaction" );
+	}
+
+	public void testBoundedMaterializedClobAccess() {
+		String original = buildRecursively( CLOB_SIZE, 'x' );
+		String changed = buildRecursively( CLOB_SIZE, 'y' );
+
+		Session s = openSession();
+		s.beginTransaction();
+		LobHolder entity = new LobHolder();
+		entity.setMaterializedClob( original );
+		s.save( entity );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		assertEquals( CLOB_SIZE, entity.getMaterializedClob().length() );
+		assertEquals( original, entity.getMaterializedClob() );
+		entity.setMaterializedClob( changed );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		assertEquals( CLOB_SIZE, entity.getMaterializedClob().length() );
+		assertEquals( changed, entity.getMaterializedClob() );
+		s.delete( entity );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testBoundedClobLocatorAccess() throws Throwable {
+		if ( skipLobLocatorTests() ) {
+			return;
+		}
+
+		String original = buildRecursively( CLOB_SIZE, 'x');
+		String changed = buildRecursively( CLOB_SIZE, 'y' );
+
+		Session s = openSession();
+		s.beginTransaction();
+		LobHolder entity = new LobHolder();
+		entity.setClobLocator( createClobLocator( s, original ) );
+		s.save( entity );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+		assertEquals( original, extractData( entity.getClobLocator() ) );
+		s.getTransaction().commit();
+		s.close();
+
+		// test mutation via setting the new clob data...
+		if ( supportsLobValueChangePropogation() ) {
+			s = openSession();
+			s.beginTransaction();
+			entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+			entity.getClobLocator().truncate( 1 );
+			entity.getClobLocator().setString( 1, changed );
+			s.getTransaction().commit();
+			s.close();
+
+			s = openSession();
+			s.beginTransaction();
+			entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+			assertNotNull( entity.getClobLocator() );
+			assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+			assertEquals( changed, extractData( entity.getClobLocator() ) );
+			entity.getClobLocator().truncate( 1 );
+			entity.getClobLocator().setString( 1, original );
+			s.getTransaction().commit();
+			s.close();
+		}
+
+		// test mutation via supplying a new clob locator instance...
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+		assertNotNull( entity.getClobLocator() );
+		assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+		assertEquals( original, extractData( entity.getClobLocator() ) );
+		entity.setClobLocator( createClobLocator( s, changed ) );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+		assertEquals( changed, extractData( entity.getClobLocator() ) );
+		s.delete( entity );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testBoundedClobLocatorAccessFromStreamUsingLength() throws Throwable {
+		if ( skipLobLocatorTests() ) {
+			return;
+		}
+
+		String original = buildRecursively( CLOB_SIZE, 'x');
+		String changed = buildRecursively( CLOB_SIZE, 'y' );
+
+		Session s = openSession();
+		s.beginTransaction();
+		LobHolder entity = new LobHolder();
+		entity.setClobLocator( createClobLocatorFromStreamUsingLength( s, original ) );
+		s.save( entity );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+		assertEquals( original, extractData( entity.getClobLocator() ) );
+		s.getTransaction().commit();
+		s.close();
+
+		// test mutation via setting the new clob data...
+		if ( supportsLobValueChangePropogation() ) {
+			s = openSession();
+			s.beginTransaction();
+			entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+			entity.getClobLocator().truncate( 1 );
+			entity.getClobLocator().setString( 1, changed );
+			s.getTransaction().commit();
+			s.close();
+
+			s = openSession();
+			s.beginTransaction();
+			entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+			assertNotNull( entity.getClobLocator() );
+			assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+			assertEquals( changed, extractData( entity.getClobLocator() ) );
+			entity.getClobLocator().truncate( 1 );
+			entity.getClobLocator().setString( 1, original );
+			s.getTransaction().commit();
+			s.close();
+		}
+
+		// test mutation via supplying a new clob locator instance...
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+		assertNotNull( entity.getClobLocator() );
+		assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+		assertEquals( original, extractData( entity.getClobLocator() ) );
+		entity.setClobLocator( createClobLocatorFromStreamUsingLength( s, changed ) );
+		s.getTransaction().commit();
+		s.close();
+
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+		assertEquals( changed, extractData( entity.getClobLocator() ) );
+		s.delete( entity );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testUnboundedClobLocatorAccess() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+
+		// Note: unbounded mutation of the underlying lob data is completely
+		// unsupported; most databases would not allow such a construct anyway.
+		// Thus here we are only testing materialization...
+
+		String original = buildRecursively( CLOB_SIZE, 'x' );
+
+		Session s = openSession();
+		s.beginTransaction();
+		LobHolder entity = new LobHolder();
+		entity.setClobLocator( createClobLocator( s, original ) );
+		s.save( entity );
+		s.getTransaction().commit();
+		s.close();
+
+		// load the entity with the clob locator, and close the session/transaction;
+		// at that point it is unbounded...
+		s = openSession();
+		s.beginTransaction();
+		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+		s.getTransaction().commit();
+		s.close();
+
+		assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+		assertEquals( original, extractData( entity.getClobLocator() ) );
+
+		s = openSession();
+		s.beginTransaction();
+		s.delete( entity );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testCreateAndAccessLobLocatorInSessionNoTransaction() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+		Session s = openSession();
+		String str = buildRecursively( CLOB_SIZE, 'x' );
+		Clob clob = createClobLocator( s, str );
+		assertEquals( CLOB_SIZE, clob.length() );
+		assertEquals( str, extractData( clob ) );
+		s.close();
+	}
+
+	public void testCreateAndAccessLobLocatorInTransaction() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+		Session s = openSession();
+		s.getTransaction().begin();
+		String str = buildRecursively( CLOB_SIZE, 'x' );
+		Clob clob = createClobLocator( s, str );
+		assertEquals( CLOB_SIZE, clob.length() );
+		assertEquals( str, extractData( clob ) );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testCreateLobLocatorInTransactionAccessOutOfTransaction() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+		Session s = openSession();
+		s.getTransaction().begin();
+		String str = buildRecursively( CLOB_SIZE, 'x' );
+		Clob clob = createClobLocator( s, str );
+		s.getTransaction().commit();
+		assertEquals( CLOB_SIZE, clob.length() );
+		assertEquals( str, extractData( clob ) );
+		s.close();
+	}
+
+	public void testCreateLobLocatorInTransactionAccessInNextTransaction() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+		Session s = openSession();
+		s.getTransaction().begin();
+		String str = buildRecursively( CLOB_SIZE, 'x' );
+		Clob clob = createClobLocator( s, str );
+		s.getTransaction().commit();
+		s.getTransaction().begin();
+		assertEquals( CLOB_SIZE, clob.length() );
+		assertEquals( str, extractData( clob ) );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	public void testCreateLobLocatorInTransactionAccessAfterSessionClose() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+		Session s = openSession();
+		s.getTransaction().begin();
+		String str = buildRecursively( CLOB_SIZE, 'x' );
+		Clob clob = createClobLocator( s, str );
+		s.getTransaction().commit();
+		s.close();
+		assertEquals( CLOB_SIZE, clob.length() );
+		assertEquals( str, extractData( clob ) );
+	}
+
+	public void testCreateLobLocatorInTransactionAccessInNextSession() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+		Session s = openSession();
+		s.getTransaction().begin();
+		String str = buildRecursively( CLOB_SIZE, 'x' );
+		Clob clob = createClobLocator( s, str );
+		s.getTransaction().commit();
+		s.close();
+		s = openSession();
+		assertEquals( CLOB_SIZE, clob.length() );
+		assertEquals( str, extractData( clob ) );
+		s.close();
+	}
+
+	public void testCreateLobLocatorInTransactionAccessInNextSessionTransaction() throws Throwable {
+		if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+			return;
+		}
+		Session s = openSession();
+		s.getTransaction().begin();
+		String str = buildRecursively( CLOB_SIZE, 'x' );
+		Clob clob = createClobLocator( s, str );
+		s.getTransaction().commit();
+		s.close();
+		s = openSession();
+		s.getTransaction().begin();
+		assertEquals( CLOB_SIZE, clob.length() );
+		assertEquals( str, extractData( clob ) );
+		s.getTransaction().commit();
+		s.close();
+	}
+
+	protected String extractData(Clob clob) throws Throwable {
+		if ( getDialect() instanceof H2Dialect ) {
+			return clob.getSubString( 1, ( int ) clob.length() );
+		}
+		else {
+			char[] data = new char[ (int) clob.length() ];
+			clob.getCharacterStream().read( data );
+			return new String( data );
+		}
+	}
+
+	protected String buildRecursively(int size, char baseChar) {
+		StringBuffer buff = new StringBuffer();
+		for( int i = 0; i < size; i++ ) {
+			buff.append( baseChar );
+		}
+		return buff.toString();
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorDefaultTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorDefaultTest.java	                        (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorDefaultTest.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,65 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.lob;
+
+import java.sql.SQLException;
+
+import junit.framework.Test;
+
+import org.hibernate.lob.LobCreatorImplJDBC4;
+import org.hibernate.lob.LobCreatorImplJDBC3;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * This class extends AbstractBlobFromLobCreatorTest to provide logic to
+ * determine if the correct LobCreator impl is used when
+ * Environment.USE_CONNECTION_FOR_LOB_CREATION is not set. The actual impl
+ * will depend on whether the JVM and driver support creating LOBs using
+ * the connection.
+ *
+ * @author Gail Badner
+ */
+public class BlobFromLobCreatorDefaultTest extends AbstractBlobFromLobCreatorTest {
+
+	public BlobFromLobCreatorDefaultTest(String name) {
+		super( name );
+	}
+
+	protected Boolean getUseConnectionForLobCreationPropertyValue() {
+		return null;
+	}
+
+	protected Class getExpectedLobCreatorClass() throws SQLException {
+		return ( jvmAndDriverSupportUseConnectionForLobCreation() ?
+				LobCreatorImplJDBC4.class :
+				LobCreatorImplJDBC3.class 
+		);
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( BlobFromLobCreatorDefaultTest.class );
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3ConnRelOnCloseTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3ConnRelOnCloseTest.java	                        (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3ConnRelOnCloseTest.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,54 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.lob;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+
+/**
+ * This class extends BlobFromLobCreatorJDBC3Test to run tests
+ * using connection release mode "on_close".
+ *
+ * @author Gail Badner
+ */
+public class BlobFromLobCreatorJDBC3ConnRelOnCloseTest extends BlobFromLobCreatorJDBC3Test {
+
+	public BlobFromLobCreatorJDBC3ConnRelOnCloseTest(String name) {
+		super( name );
+	}
+
+	public void configure(Configuration cfg) {
+		super.configure( cfg );
+		cfg.setProperty( Environment.RELEASE_CONNECTIONS, "on_close" );
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( BlobFromLobCreatorJDBC3ConnRelOnCloseTest.class );
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3Test.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3Test.java	                        (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3Test.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,59 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.lob;
+
+import junit.framework.Test;
+
+import org.hibernate.lob.LobCreatorImplJDBC3;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * This class extends AbstractBlobFromLobCreatorTest to determine if the
+ * correct LobCreator impl is used when Environment.USE_CONNECTION_FOR_LOB_CREATION
+ * is set to false. The actual impl should be the JDBC3 LobCreator, even when
+ * the JVM and JDBC driver support JDBC4. The JDBC3 LobCreator does not use the
+ * Connection to create LOBs.
+ *
+ * @author Gail Badner
+ */
+public class BlobFromLobCreatorJDBC3Test extends AbstractBlobFromLobCreatorTest {
+
+	public BlobFromLobCreatorJDBC3Test(String name) {
+		super( name );
+	}
+
+	protected Boolean getUseConnectionForLobCreationPropertyValue() {
+		return Boolean.FALSE;
+	}
+
+	protected Class getExpectedLobCreatorClass() {
+		return LobCreatorImplJDBC3.class;
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( BlobFromLobCreatorJDBC3Test.class );
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4ConnRelOnCloseTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4ConnRelOnCloseTest.java	                        (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4ConnRelOnCloseTest.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,54 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.lob;
+
+import junit.framework.Test;
+
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * This class extends BlobFromLobCreatorJDBC4Test to run tests
+ * using connection release mode "on_close".
+ *
+ * @author Gail Badner
+ */
+public class BlobFromLobCreatorJDBC4ConnRelOnCloseTest extends BlobFromLobCreatorJDBC4Test {
+
+	public BlobFromLobCreatorJDBC4ConnRelOnCloseTest(String name) {
+		super( name );
+	}
+
+	public void configure(Configuration cfg) {
+		super.configure( cfg );
+		cfg.setProperty( Environment.RELEASE_CONNECTIONS, "on_close" );
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( BlobFromLobCreatorJDBC4ConnRelOnCloseTest.class );
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4Test.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4Test.java	                        (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4Test.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,112 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.lob;
+
+import java.sql.SQLException;
+import java.sql.Blob;
+
+import junit.framework.Test;
+
+import org.hibernate.lob.LobCreatorImplJDBC4;
+import org.hibernate.cfg.Environment;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.Session;
+import org.hibernate.HibernateException;
+
+/**
+ * This class extends AbstractBlobFromLobCreatorTest to determine if the
+ * correct LobCreator impl is used when Environment.USE_CONNECTION_FOR_LOB_CREATION
+ * is set to true. The actual impl should be the JDBC4 LobCreator, even when
+ * the JVM and/or JDBC driver do not support JDBC4. The JDBC4 LobCreator uses the
+ * Connection to create LOBs.
+ *
+ * @author Gail Badner
+ */
+public class BlobFromLobCreatorJDBC4Test extends AbstractBlobFromLobCreatorTest {
+
+	public BlobFromLobCreatorJDBC4Test(String name) {
+		super( name );
+	}
+
+	protected Boolean getUseConnectionForLobCreationPropertyValue() {
+		return Boolean.TRUE;
+	}
+
+	protected Class getExpectedLobCreatorClass() {
+		return LobCreatorImplJDBC4.class;
+	}
+	
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( BlobFromLobCreatorJDBC4Test.class );
+	}
+
+	protected boolean skipLobLocatorTests()  throws SQLException {
+		if ( ! Environment.jvmSupportsJDBC4() ) {
+			reportSkip( "JVM does not support creating LOBs using the connection", "LOB support" );
+			return true;
+		}
+		if ( ! jvmAndDriverSupportUseConnectionForLobCreation() ) {
+			reportSkip( "Driver does not support creating LOBs using the connection", "LOB support" );
+			return true;
+		}
+		return false;
+	}
+
+	public void testCreateBlobLocatorSupport() throws Throwable {
+		Session s = openSession();
+		s.getTransaction().begin();
+		byte[] bytes = buildRecursively( BLOB_SIZE, true );
+		try {
+			Blob blob = createBlobLocator( s, bytes );
+			if ( ! Environment.jvmSupportsJDBC4() ) {
+				fail( "should have thrown NoSuchMethodException" );
+			}
+			else if ( ! jvmAndDriverSupportUseConnectionForLobCreation() ) {
+				fail( "should have thrown AbstractMethodException" );
+			}
+			assertEquals( bytes, extractData( blob ) );
+			s.getTransaction().commit();
+		}
+		catch( HibernateException e ) {
+			s.getTransaction().rollback();
+			if ( e.getCause() instanceof NoSuchMethodException ) {
+				assertTrue( ! Environment.jvmSupportsJDBC4() &&
+						isUseConnectionForLobCreationEnabled() );
+			}
+			else if ( e.getCause() instanceof AbstractMethodError ) {
+				assertTrue( Environment.jvmSupportsJDBC4() &&
+						! jvmAndDriverSupportUseConnectionForLobCreation() &&
+						isUseConnectionForLobCreationEnabled() );
+			}
+			else {
+				throw e;
+			}
+		}
+		finally {
+			s.close();
+		}
+	}
+}
\ No newline at end of file

Modified: core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobTest.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobTest.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -1,200 +1,67 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
 package org.hibernate.test.lob;
 
 import java.sql.Blob;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
 
-import junit.framework.AssertionFailedError;
 import junit.framework.Test;
 
 import org.hibernate.Hibernate;
-import org.hibernate.LockMode;
 import org.hibernate.Session;
-import org.hibernate.dialect.Dialect;
-import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
 import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
-import org.hibernate.util.ArrayHelper;
 
 /**
- * {@inheritDoc}
+ * This class extends AbstractBlobTest so that LOBs are created using the
+ * Hibernate.createBlob() APIs. These APIs do not use the connection to
+ * create LOBs.
  *
  * @author Steve Ebersole
  */
-public class BlobTest extends DatabaseSpecificFunctionalTestCase {
-	private static final int BLOB_SIZE = 10000;
+public class BlobTest extends AbstractBlobTest {
 
 	public BlobTest(String name) {
 		super( name );
 	}
 
-	public String[] getMappings() {
-		return new String[] { "lob/LobMappings.hbm.xml" };
-	}
-
 	public static Test suite() {
 		return new FunctionalTestClassTestSuite( BlobTest.class );
 	}
 
-	public boolean appliesTo(Dialect dialect) {
-		if ( ! dialect.supportsExpectedLobUsagePattern() ) {
-			reportSkip( "database/driver does not support expected LOB usage pattern", "LOB support" );
-			return false;
-		}
-		return true;
+	protected Blob createBlobLocator(Session s, byte[] bytes) {
+		return Hibernate.createBlob( bytes );
 	}
 
-	public void testBoundedMaterializedBlobAccess() {
-		byte[] original = buildRecursively( BLOB_SIZE, true );
-		byte[] changed = buildRecursively( BLOB_SIZE, false );
-
-		Session s = openSession();
-		s.beginTransaction();
-		LobHolder entity = new LobHolder();
-		entity.setMaterializedBlob( original );
-		s.save( entity );
-		s.getTransaction().commit();
-		s.close();
-
-		s = openSession();
-		s.beginTransaction();
-		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
-		assertEquals( BLOB_SIZE, entity.getMaterializedBlob().length );
-		assertEquals( original, entity.getMaterializedBlob() );
-		entity.setMaterializedBlob( changed );
-		s.getTransaction().commit();
-		s.close();
-
-		s = openSession();
-		s.beginTransaction();
-		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
-		assertEquals( BLOB_SIZE, entity.getMaterializedBlob().length );
-		assertEquals( changed, entity.getMaterializedBlob() );
-		s.delete( entity );
-		s.getTransaction().commit();
-		s.close();
+	protected Blob createBlobLocatorFromStream(Session s, byte[] bytes) throws IOException {
+		return Hibernate.createBlob( new ByteArrayInputStream( bytes ) );
 	}
 
-	public void testBoundedBlobLocatorAccess() throws Throwable {
-		byte[] original = buildRecursively( BLOB_SIZE, true );
-		byte[] changed = buildRecursively( BLOB_SIZE, false );
-
-		Session s = openSession();
-		s.beginTransaction();
-		LobHolder entity = new LobHolder();
-		entity.setBlobLocator( Hibernate.createBlob( original ) );
-		s.save( entity );
-		s.getTransaction().commit();
-		s.close();
-
-		s = openSession();
-		s.beginTransaction();
-		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
-		assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
-		assertEquals( original, extractData( entity.getBlobLocator() ) );
-		s.getTransaction().commit();
-		s.close();
-
-		// test mutation via setting the new clob data...
-		if ( supportsLobValueChangePropogation() ) {
-			s = openSession();
-			s.beginTransaction();
-			entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
-			entity.getBlobLocator().truncate( 1 );
-			entity.getBlobLocator().setBytes( 1, changed );
-			s.getTransaction().commit();
-			s.close();
-
-			s = openSession();
-			s.beginTransaction();
-			entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
-			assertNotNull( entity.getBlobLocator() );
-			assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
-			assertEquals( changed, extractData( entity.getBlobLocator() ) );
-			entity.getBlobLocator().truncate( 1 );
-			entity.getBlobLocator().setBytes( 1, original );
-			s.getTransaction().commit();
-			s.close();
-		}
-
-		// test mutation via supplying a new clob locator instance...
-		s = openSession();
-		s.beginTransaction();
-		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
-		assertNotNull( entity.getBlobLocator() );
-		assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
-		assertEquals( original, extractData( entity.getBlobLocator() ) );
-		entity.setBlobLocator( Hibernate.createBlob( changed ) );
-		s.getTransaction().commit();
-		s.close();
-
-		s = openSession();
-		s.beginTransaction();
-		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
-		assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
-		assertEquals( changed, extractData( entity.getBlobLocator() ) );
-		s.delete( entity );
-		s.getTransaction().commit();
-		s.close();
-
+	protected Blob createBlobLocatorFromStreamUsingLength(Session s, byte[] bytes) throws IOException {
+		return Hibernate.createBlob( new ByteArrayInputStream( bytes ), bytes.length );
 	}
-
-	public void testUnboundedBlobLocatorAccess() throws Throwable {
-		if ( ! supportsUnboundedLobLocatorMaterialization() ) {
-			return;
-		}
-
-		// Note: unbounded mutation of the underlying lob data is completely
-		// unsupported; most databases would not allow such a construct anyway.
-		// Thus here we are only testing materialization...
-
-		byte[] original = buildRecursively( BLOB_SIZE, true );
-
-		Session s = openSession();
-		s.beginTransaction();
-		LobHolder entity = new LobHolder();
-		entity.setBlobLocator( Hibernate.createBlob( original ) );
-		s.save( entity );
-		s.getTransaction().commit();
-		s.close();
-
-		// load the entity with the clob locator, and close the session/transaction;
-		// at that point it is unbounded...
-		s = openSession();
-		s.beginTransaction();
-		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
-		s.getTransaction().commit();
-		s.close();
-
-		assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
-		assertEquals( original, extractData( entity.getBlobLocator() ) );
-
-		s = openSession();
-		s.beginTransaction();
-		s.delete( entity );
-		s.getTransaction().commit();
-		s.close();
-	}
-
-	private byte[] extractData(Blob blob) throws Throwable {
-		return blob.getBytes( 1, ( int ) blob.length() );
-	}
-
-
-	private byte[] buildRecursively(int size, boolean on) {
-		byte[] data = new byte[size];
-		data[0] = mask( on );
-		for ( int i = 0; i < size; i++ ) {
-			data[i] = mask( on );
-			on = !on;
-		}
-		return data;
-	}
-
-	private byte mask(boolean on) {
-		return on ? ( byte ) 1 : ( byte ) 0;
-	}
-
-	public static void assertEquals(byte[] val1, byte[] val2) {
-		if ( !ArrayHelper.isEquals( val1, val2 ) ) {
-			throw new AssertionFailedError( "byte arrays did not match" );
-		}
-	}
 }
+

Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorDefaultTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorDefaultTest.java	                        (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorDefaultTest.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,65 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.lob;
+
+import java.sql.SQLException;
+
+import junit.framework.Test;
+
+import org.hibernate.lob.LobCreatorImplJDBC4;
+import org.hibernate.lob.LobCreatorImplJDBC3;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * This class extends AbstractClobFromLobCreatorTest to provide logic to
+ * determine if the correct LobCreator impl is used when
+ * Environment.USE_CONNECTION_FOR_LOB_CREATION is not set. The actual impl
+ * will depend on whether the JVM and driver support creating LOBs using
+ * the connection.
+ *
+ * @author Gail Badner
+ */
+public class ClobFromLobCreatorDefaultTest extends AbstractClobFromLobCreatorTest {
+
+	public ClobFromLobCreatorDefaultTest(String name) {
+		super( name );
+	}
+
+	protected Boolean getUseConnectionForLobCreationPropertyValue() {
+		return null;
+	}
+
+	protected Class getExpectedLobCreatorClass() throws SQLException {
+		return ( jvmAndDriverSupportUseConnectionForLobCreation() ?
+				LobCreatorImplJDBC4.class :
+				LobCreatorImplJDBC3.class
+		);
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( ClobFromLobCreatorDefaultTest.class );
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3ConnRelOnCloseTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3ConnRelOnCloseTest.java	                        (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3ConnRelOnCloseTest.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,54 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.lob;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+
+/**
+ * This class extends ClobFromLobCreatorJDBC3Test to run tests
+ * using connection release mode "on_close".
+ *
+ * @author Gail Badner
+ */
+public class ClobFromLobCreatorJDBC3ConnRelOnCloseTest extends ClobFromLobCreatorJDBC3Test {
+
+	public ClobFromLobCreatorJDBC3ConnRelOnCloseTest(String name) {
+		super( name );
+	}
+
+	public void configure(Configuration cfg) {
+		super.configure( cfg );
+		cfg.setProperty( Environment.RELEASE_CONNECTIONS, "on_close" );
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( ClobFromLobCreatorJDBC3ConnRelOnCloseTest.class );
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3Test.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3Test.java	                        (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3Test.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,59 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.lob;
+
+import junit.framework.Test;
+
+import org.hibernate.lob.LobCreatorImplJDBC3;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * This class extends AbstractClobFromLobCreatorTest to determine if the
+ * correct LobCreator impl is used when Environment.USE_CONNECTION_FOR_LOB_CREATION
+ * is set to false. The actual impl should be the JDBC3 LobCreator, even when
+ * the JVM and JDBC driver support JDBC4. The JDBC3 LobCreator does not use the
+ * Connection to create LOBs.
+ *
+ * @author Gail Badner
+ */
+public class ClobFromLobCreatorJDBC3Test extends AbstractClobFromLobCreatorTest {
+
+	public ClobFromLobCreatorJDBC3Test(String name) {
+		super( name );
+	}
+
+	protected Boolean getUseConnectionForLobCreationPropertyValue() {
+		return Boolean.FALSE;
+	}
+
+	protected Class getExpectedLobCreatorClass() {
+		return LobCreatorImplJDBC3.class;
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( ClobFromLobCreatorJDBC3Test.class );
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4ConnRelOnCloseTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4ConnRelOnCloseTest.java	                        (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4ConnRelOnCloseTest.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,54 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.lob;
+
+import junit.framework.Test;
+
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * This class extends ClobFromLobCreatorJDBC4Test to run tests
+ * using connection release mode "on_close".
+ *
+ * @author Gail Badner
+ */
+public class ClobFromLobCreatorJDBC4ConnRelOnCloseTest extends ClobFromLobCreatorJDBC4Test {
+
+	public ClobFromLobCreatorJDBC4ConnRelOnCloseTest(String name) {
+		super( name );
+	}
+
+	public void configure(Configuration cfg) {
+		super.configure( cfg );
+		cfg.setProperty( Environment.RELEASE_CONNECTIONS, "on_close" );
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( ClobFromLobCreatorJDBC4ConnRelOnCloseTest.class );
+	}
+}
\ No newline at end of file

Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4Test.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4Test.java	                        (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4Test.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -0,0 +1,112 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.test.lob;
+
+import java.sql.SQLException;
+import java.sql.Clob;
+
+import junit.framework.Test;
+
+import org.hibernate.lob.LobCreatorImplJDBC4;
+import org.hibernate.cfg.Environment;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.Session;
+import org.hibernate.HibernateException;
+
+/**
+ * This class extends AbstractClobFromLobCreatorTest to determine if the
+ * correct LobCreator impl is used when Environment.USE_CONNECTION_FOR_LOB_CREATION
+ * is set to true. The actual impl should be the JDBC4 LobCreator, even when
+ * the JVM and/or JDBC driver do not support JDBC4. The JDBC4 LobCreator uses the
+ * Connection to create LOBs.
+ *
+ * @author Gail Badner
+ */
+public class ClobFromLobCreatorJDBC4Test extends AbstractClobFromLobCreatorTest {
+
+	public ClobFromLobCreatorJDBC4Test(String name) {
+		super( name );
+	}
+
+	protected Boolean getUseConnectionForLobCreationPropertyValue() {
+		return Boolean.TRUE;
+	}
+
+	protected Class getExpectedLobCreatorClass() {
+		return LobCreatorImplJDBC4.class;
+	}
+
+	public static Test suite() {
+		return new FunctionalTestClassTestSuite( ClobFromLobCreatorJDBC4Test.class );
+	}
+
+	protected boolean skipLobLocatorTests()  throws SQLException {
+		if ( ! Environment.jvmSupportsJDBC4() ) {
+			reportSkip( "JVM does not support creating LOBs using the connection", "LOB support" );
+			return true;
+		}
+		if ( ! jvmAndDriverSupportUseConnectionForLobCreation() ) {
+			reportSkip( "Driver does not support creating LOBs using the connection", "LOB support" );
+			return true;
+		}
+		return false;
+	}
+
+	public void testCreateClobLocatorSupport() throws Throwable {
+		Session s = openSession();
+		s.getTransaction().begin();
+		String str = buildRecursively( CLOB_SIZE, 'x' );
+		try {
+			Clob clob = createClobLocator( s, str );
+			if ( ! Environment.jvmSupportsJDBC4() ) {
+				fail( "should have thrown NoSuchMethodException" );
+			}
+			else if ( ! jvmAndDriverSupportUseConnectionForLobCreation() ) {
+				fail( "should have thrown AbstractMethodException" );
+			}
+			assertEquals( str, extractData( clob ) );
+			s.getTransaction().commit();
+		}
+		catch( HibernateException e ) {
+			s.getTransaction().rollback();
+			if ( e.getCause() instanceof NoSuchMethodException ) {
+				assertTrue( ! Environment.jvmSupportsJDBC4() &&
+						isUseConnectionForLobCreationEnabled() );
+			}
+			else if ( e.getCause() instanceof AbstractMethodError ) {
+				assertTrue( Environment.jvmSupportsJDBC4() &&
+						! jvmAndDriverSupportUseConnectionForLobCreation() &&
+						isUseConnectionForLobCreationEnabled() );
+			}
+			else {
+				throw e;
+			}
+		}
+		finally {
+			s.close();
+		}
+	}
+}
\ No newline at end of file

Modified: core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobTest.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobTest.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -1,196 +1,62 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
 package org.hibernate.test.lob;
 
 import java.sql.Clob;
+import java.io.IOException;
+import java.io.StringReader;
 
 import junit.framework.Test;
 
 import org.hibernate.Hibernate;
-import org.hibernate.LockMode;
 import org.hibernate.Session;
-import org.hibernate.dialect.Dialect;
-import org.hibernate.dialect.H2Dialect;
-import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
 import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
 
 /**
- * Test various access scenarios for eager and lazy materialization
- * of CLOB data, as well as bounded and unbounded materialization
- * and mutation.
+ * This class extends AbstractClobTest so that LOBs are created using the
+ * Hibernate.createClob() APIs. These APIs do not use the connection to
+ * create LOBs.
  *
  * @author Steve Ebersole
  */
-public class ClobTest extends DatabaseSpecificFunctionalTestCase {
-	private static final int CLOB_SIZE = 10000;
+public class ClobTest extends AbstractClobTest {
 
 	public ClobTest(String name) {
 		super( name );
 	}
 
-	public String[] getMappings() {
-		return new String[] { "lob/LobMappings.hbm.xml" };
-	}
-
 	public static Test suite() {
 		return new FunctionalTestClassTestSuite( ClobTest.class );
 	}
 
-	public boolean appliesTo(Dialect dialect) {
-		if ( ! dialect.supportsExpectedLobUsagePattern() ) {
-			reportSkip( "database/driver does not support expected LOB usage pattern", "LOB support" );
-			return false;
-		}
-		return true;
+	protected Clob createClobLocator(Session s, String str) {
+		return Hibernate.createClob( str );
 	}
 
-	public void testBoundedMaterializedClobAccess() {
-		String original = buildRecursively( CLOB_SIZE, 'x' );
-		String changed = buildRecursively( CLOB_SIZE, 'y' );
-
-		Session s = openSession();
-		s.beginTransaction();
-		LobHolder entity = new LobHolder();
-		entity.setMaterializedClob( original );
-		s.save( entity );
-		s.getTransaction().commit();
-		s.close();
-
-		s = openSession();
-		s.beginTransaction();
-		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
-		assertEquals( CLOB_SIZE, entity.getMaterializedClob().length() );
-		assertEquals( original, entity.getMaterializedClob() );
-		entity.setMaterializedClob( changed );
-		s.getTransaction().commit();
-		s.close();
-
-		s = openSession();
-		s.beginTransaction();
-		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
-		assertEquals( CLOB_SIZE, entity.getMaterializedClob().length() );
-		assertEquals( changed, entity.getMaterializedClob() );
-		s.delete( entity );
-		s.getTransaction().commit();
-		s.close();
+	protected Clob createClobLocatorFromStreamUsingLength(Session s, String str) throws IOException {
+		return Hibernate.createClob( new StringReader( str ), str.length() );
 	}
-
-	public void testBoundedClobLocatorAccess() throws Throwable {
-		String original = buildRecursively( CLOB_SIZE, 'x' );
-		String changed = buildRecursively( CLOB_SIZE, 'y' );
-
-		Session s = openSession();
-		s.beginTransaction();
-		LobHolder entity = new LobHolder();
-		entity.setClobLocator( Hibernate.createClob( original ) );
-		s.save( entity );
-		s.getTransaction().commit();
-		s.close();
-
-		s = openSession();
-		s.beginTransaction();
-		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
-		assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
-		assertEquals( original, extractData( entity.getClobLocator() ) );
-		s.getTransaction().commit();
-		s.close();
-
-		// test mutation via setting the new clob data...
-		if ( supportsLobValueChangePropogation() ) {
-			s = openSession();
-			s.beginTransaction();
-			entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
-			entity.getClobLocator().truncate( 1 );
-			entity.getClobLocator().setString( 1, changed );
-			s.getTransaction().commit();
-			s.close();
-
-			s = openSession();
-			s.beginTransaction();
-			entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
-			assertNotNull( entity.getClobLocator() );
-			assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
-			assertEquals( changed, extractData( entity.getClobLocator() ) );
-			entity.getClobLocator().truncate( 1 );
-			entity.getClobLocator().setString( 1, original );
-			s.getTransaction().commit();
-			s.close();
-		}
-
-		// test mutation via supplying a new clob locator instance...
-		s = openSession();
-		s.beginTransaction();
-		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
-		assertNotNull( entity.getClobLocator() );
-		assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
-		assertEquals( original, extractData( entity.getClobLocator() ) );
-		entity.setClobLocator( Hibernate.createClob( changed ) );
-		s.getTransaction().commit();
-		s.close();
-
-		s = openSession();
-		s.beginTransaction();
-		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
-		assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
-		assertEquals( changed, extractData( entity.getClobLocator() ) );
-		s.delete( entity );
-		s.getTransaction().commit();
-		s.close();
-
-	}
-
-	public void testUnboundedClobLocatorAccess() throws Throwable {
-		if ( ! supportsUnboundedLobLocatorMaterialization() ) {
-			return;
-		}
-
-		// Note: unbounded mutation of the underlying lob data is completely
-		// unsupported; most databases would not allow such a construct anyway.
-		// Thus here we are only testing materialization...
-
-		String original = buildRecursively( CLOB_SIZE, 'x' );
-
-		Session s = openSession();
-		s.beginTransaction();
-		LobHolder entity = new LobHolder();
-		entity.setClobLocator( Hibernate.createClob( original ) );
-		s.save( entity );
-		s.getTransaction().commit();
-		s.close();
-
-		// load the entity with the clob locator, and close the session/transaction;
-		// at that point it is unbounded...
-		s = openSession();
-		s.beginTransaction();
-		entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
-		s.getTransaction().commit();
-		s.close();
-
-		assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
-		assertEquals( original, extractData( entity.getClobLocator() ) );
-
-		s = openSession();
-		s.beginTransaction();
-		s.delete( entity );
-		s.getTransaction().commit();
-		s.close();
-	}
-
-	private String extractData(Clob clob) throws Throwable {
-		if ( getDialect() instanceof H2Dialect ) {
-			return clob.getSubString( 1, ( int ) clob.length() );
-		}
-		else {
-			char[] data = new char[ (int) clob.length() ];
-			clob.getCharacterStream().read( data );
-			return new String( data );
-		}
-	}
-
-
-	private String buildRecursively(int size, char baseChar) {
-		StringBuffer buff = new StringBuffer();
-		for( int i = 0; i < size; i++ ) {
-			buff.append( baseChar );
-		}
-		return buff.toString();
-	}
-}
+}
\ No newline at end of file

Modified: core/branches/Branch_3_2/test/org/hibernate/test/lob/LobHolder.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/LobHolder.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/LobHolder.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -1,3 +1,28 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
 package org.hibernate.test.lob;
 
 import java.io.Serializable;

Modified: core/branches/Branch_3_2/test/org/hibernate/test/lob/MaterializedBlobType.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/MaterializedBlobType.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/MaterializedBlobType.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -1,3 +1,28 @@
+//$Id: $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
 package org.hibernate.test.lob;
 
 import java.sql.Types;

Modified: core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableData.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableData.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableData.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -1,4 +1,28 @@
-// $Id$
+//$Id$
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
 package org.hibernate.test.lob;
 
 import java.io.Serializable;

Modified: core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableTypeTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableTypeTest.java	2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableTypeTest.java	2008-10-29 05:38:54 UTC (rev 15430)
@@ -1,4 +1,28 @@
-// $Id$
+//$Id$
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
 package org.hibernate.test.lob;
 
 import junit.framework.Test;




More information about the hibernate-commits mailing list