|
From: <hib...@li...> - 2006-06-10 03:24:14
|
Author: epbernard
Date: 2006-06-09 23:24:05 -0400 (Fri, 09 Jun 2006)
New Revision: 10009
Added:
trunk/Hibernate3/src/org/hibernate/type/AbstractBynaryType.java
trunk/Hibernate3/src/org/hibernate/type/AbstractCharArrayType.java
trunk/Hibernate3/src/org/hibernate/type/CharArrayType.java
trunk/Hibernate3/src/org/hibernate/type/CharacterArrayType.java
trunk/Hibernate3/src/org/hibernate/type/WrapperBinaryType.java
Modified:
trunk/Hibernate3/etc/log4j.properties
trunk/Hibernate3/src/org/hibernate/Hibernate.java
trunk/Hibernate3/src/org/hibernate/type/BinaryType.java
trunk/Hibernate3/src/org/hibernate/type/TypeFactory.java
Log:
HHH-1826 built in support for Byte[] Character[] char[]
Modified: trunk/Hibernate3/etc/log4j.properties
===================================================================
--- trunk/Hibernate3/etc/log4j.properties 2006-06-09 17:46:51 UTC (rev 10008)
+++ trunk/Hibernate3/etc/log4j.properties 2006-06-10 03:24:05 UTC (rev 10009)
@@ -14,8 +14,8 @@
log4j.rootLogger=warn, stdout
-log4j.logger.org.hibernate=info
-#log4j.logger.org.hibernate=debug
+#log4j.logger.org.hibernate=info
+log4j.logger.org.hibernate=debug
### log HQL query parser activity
#log4j.logger.org.hibernate.hql.ast.AST=debug
Modified: trunk/Hibernate3/src/org/hibernate/Hibernate.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/Hibernate.java 2006-06-09 17:46:51 UTC (rev 10008)
+++ trunk/Hibernate3/src/org/hibernate/Hibernate.java 2006-06-10 03:24:05 UTC (rev 10009)
@@ -53,6 +53,9 @@
import org.hibernate.type.TrueFalseType;
import org.hibernate.type.Type;
import org.hibernate.type.YesNoType;
+import org.hibernate.type.CharArrayType;
+import org.hibernate.type.WrapperBinaryType;
+import org.hibernate.type.CharacterArrayType;
import org.hibernate.usertype.CompositeUserType;
/**
@@ -140,6 +143,18 @@
*/
public static final NullableType BINARY = new BinaryType();
/**
+ * Hibernate <tt>wrapper-binary</tt> type.
+ */
+ public static final NullableType WRAPPER_BINARY = new WrapperBinaryType();
+ /**
+ * Hibernate char[] type.
+ */
+ public static final NullableType CHAR_ARRAY = new CharArrayType();
+ /**
+ * Hibernate Character[] type.
+ */
+ public static final NullableType CHARACTER_ARRAY = new CharacterArrayType();
+ /**
* Hibernate <tt>text</tt> type.
*/
public static final NullableType TEXT = new TextType();
Added: trunk/Hibernate3/src/org/hibernate/type/AbstractBynaryType.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/type/AbstractBynaryType.java 2006-06-09 17:46:51 UTC (rev 10008)
+++ trunk/Hibernate3/src/org/hibernate/type/AbstractBynaryType.java 2006-06-10 03:24:05 UTC (rev 10009)
@@ -0,0 +1,166 @@
+//$Id: $
+package org.hibernate.type;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.ResultSet;
+import java.sql.Types;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Comparator;
+
+import org.hibernate.HibernateException;
+import org.hibernate.EntityMode;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.cfg.Environment;
+
+/**
+ * Logic to bind stream of byte into a VARBINARY
+ *
+ * @author Gavin King
+ * @author Emmanuel Bernard
+ */
+public abstract class AbstractBynaryType extends MutableType implements VersionType, Comparator {
+
+ /**
+ * Convert the byte[] into the expected object type
+ */
+ abstract protected Object toExternalFormat(byte[] bytes);
+
+ /**
+ * Convert the object into the internal byte[] representation
+ */
+ abstract protected byte[] toInternalFormat(Object bytes);
+
+ public void set(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
+ byte[] internalValue = toInternalFormat( value );
+ if ( Environment.useStreamsForBinary() ) {
+ st.setBinaryStream( index, new ByteArrayInputStream( internalValue ), internalValue.length );
+ }
+ else {
+ st.setBytes( index, internalValue );
+ }
+ }
+
+ public Object get(ResultSet rs, String name) throws HibernateException, SQLException {
+
+ if ( Environment.useStreamsForBinary() ) {
+
+ InputStream inputStream = rs.getBinaryStream(name);
+
+ if (inputStream==null) return toExternalFormat( null ); // is this really necessary?
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(2048);
+ byte[] buffer = new byte[2048];
+
+ try {
+ while (true) {
+ int amountRead = inputStream.read(buffer);
+ if (amountRead == -1) {
+ break;
+ }
+ outputStream.write(buffer, 0, amountRead);
+ }
+
+ inputStream.close();
+ outputStream.close();
+ }
+ catch (IOException ioe) {
+ throw new HibernateException( "IOException occurred reading a binary value", ioe );
+ }
+
+ return toExternalFormat( outputStream.toByteArray() );
+
+ }
+ else {
+ return toExternalFormat( rs.getBytes(name) );
+ }
+ }
+
+ public int sqlType() {
+ return Types.VARBINARY;
+ }
+
+ // VersionType impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // Note : simply returns null for seed() and next() as the only known
+ // application of binary types for versioning is for use with the
+ // TIMESTAMP datatype supported by Sybase and SQL Server, which
+ // are completely db-generated values...
+ public Object seed(SessionImplementor session) {
+ return null;
+ }
+
+ public Object next(Object current, SessionImplementor session) {
+ return current;
+ }
+
+ public Comparator getComparator() {
+ return this;
+ }
+
+ public int compare(Object o1, Object o2) {
+ return compare( o1, o2, null );
+ }
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ public boolean isEqual(Object x, Object y) {
+ return x==y || ( x!=null && y!=null && java.util.Arrays.equals( toInternalFormat(x), toInternalFormat(y) ) );
+ }
+
+ public int getHashCode(Object x, EntityMode entityMode) {
+ byte[] bytes = toInternalFormat(x);
+ int hashCode = 1;
+ for ( int j=0; j<bytes.length; j++ ) {
+ hashCode = 31 * hashCode + bytes[j];
+ }
+ return hashCode;
+ }
+
+ public int compare(Object x, Object y, EntityMode entityMode) {
+ byte[] xbytes = toInternalFormat(x);
+ byte[] ybytes = toInternalFormat(y);
+ if ( xbytes.length < ybytes.length ) return -1;
+ if ( xbytes.length > ybytes.length ) return 1;
+ for ( int i=0; i<xbytes.length; i++ ) {
+ if ( xbytes[i] < ybytes[i] ) return -1;
+ if ( xbytes[i] > ybytes[i] ) return 1;
+ }
+ return 0;
+ }
+
+ public abstract String getName();
+
+ public String toString(Object val) {
+ byte[] bytes = toInternalFormat(val);
+ StringBuffer buf = new StringBuffer();
+ for ( int i=0; i<bytes.length; i++ ) {
+ String hexStr = Integer.toHexString( bytes[i] - Byte.MIN_VALUE );
+ if ( hexStr.length()==1 ) buf.append('0');
+ buf.append(hexStr);
+ }
+ return buf.toString();
+ }
+
+ public Object deepCopyNotNull(Object value) {
+ byte[] bytes = toInternalFormat(value);
+ byte[] result = new byte[bytes.length];
+ System.arraycopy(bytes, 0, result, 0, bytes.length);
+ return toExternalFormat(result);
+ }
+
+ public Object fromStringValue(String xml) throws HibernateException {
+ if (xml == null)
+ return null;
+ if (xml.length() % 2 != 0)
+ throw new IllegalArgumentException("The string is not a valid xml representation of a binary content.");
+ byte[] bytes = new byte[xml.length() / 2];
+ for (int i = 0; i < bytes.length; i++) {
+ String hexStr = xml.substring(i * 2, (i + 1) * 2);
+ bytes[i] = (byte) (Integer.parseInt(hexStr, 16) + Byte.MIN_VALUE);
+ }
+ return toExternalFormat(bytes);
+ }
+
+}
Added: trunk/Hibernate3/src/org/hibernate/type/AbstractCharArrayType.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/type/AbstractCharArrayType.java 2006-06-09 17:46:51 UTC (rev 10008)
+++ trunk/Hibernate3/src/org/hibernate/type/AbstractCharArrayType.java 2006-06-10 03:24:05 UTC (rev 10009)
@@ -0,0 +1,96 @@
+//$Id: $
+package org.hibernate.type;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.PreparedStatement;
+import java.sql.Types;
+import java.io.Reader;
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.io.CharArrayReader;
+
+import org.hibernate.HibernateException;
+import org.hibernate.dialect.Dialect;
+
+/**
+ * Logic to bind stream of char into a VARCHAR
+ *
+ * @author Emmanuel Bernard
+ */
+public abstract class AbstractCharArrayType extends MutableType {
+
+ /**
+ * Convert the char[] into the expected object type
+ */
+ abstract protected Object toExternalFormat(char[] chars);
+
+ /**
+ * Convert the object into the internal char[] representation
+ */
+ abstract protected char[] toInternalFormat(Object chars);
+
+ public Object get(ResultSet rs, String name) throws SQLException {
+ Reader stream = rs.getCharacterStream(name);
+ if ( stream == null ) return toExternalFormat( null );
+ CharArrayWriter writer = new CharArrayWriter();
+ for(;;) {
+ try {
+ int c = stream.read();
+ if ( c == -1) return toExternalFormat( writer.toCharArray() );
+ writer.write( c );
+ }
+ catch (IOException e) {
+ throw new HibernateException("Unable to read character stream from rs");
+ }
+ }
+ }
+
+ public abstract Class getReturnedClass();
+
+ public void set(PreparedStatement st, Object value, int index) throws SQLException {
+ char[] chars = toInternalFormat( value );
+ st.setCharacterStream(index, new CharArrayReader(chars), chars.length);
+ }
+
+ public int sqlType() {
+ return Types.VARCHAR;
+ }
+
+ public String objectToSQLString(Object value, Dialect dialect) throws Exception {
+
+ return '\'' + new String( toInternalFormat( value ) ) + '\'';
+ }
+
+ public Object stringToObject(String xml) throws Exception {
+ if (xml == null) return toExternalFormat( null );
+ int length = xml.length();
+ char[] chars = new char[length];
+ for (int index = 0 ; index < length ; index++ ) {
+ chars[index] = xml.charAt( index );
+ }
+ return toExternalFormat( chars );
+ }
+
+ public String toString(Object value) {
+ if (value == null) return null;
+ return new String( toInternalFormat( value ) );
+ }
+
+ public Object fromStringValue(String xml) {
+ if (xml == null) return null;
+ int length = xml.length();
+ char[] chars = new char[length];
+ for (int index = 0 ; index < length ; index++ ) {
+ chars[index] = xml.charAt( index );
+ }
+ return toExternalFormat( chars );
+ }
+
+ protected Object deepCopyNotNull(Object value) throws HibernateException {
+ char[] chars = toInternalFormat(value);
+ char[] result = new char[chars.length];
+ System.arraycopy(chars, 0, result, 0, chars.length);
+ return toExternalFormat(result);
+ }
+}
Modified: trunk/Hibernate3/src/org/hibernate/type/BinaryType.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/type/BinaryType.java 2006-06-09 17:46:51 UTC (rev 10008)
+++ trunk/Hibernate3/src/org/hibernate/type/BinaryType.java 2006-06-10 03:24:05 UTC (rev 10009)
@@ -1,157 +1,24 @@
//$Id$
package org.hibernate.type;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Types;
-import java.util.Comparator;
-
-import org.hibernate.EntityMode;
-import org.hibernate.HibernateException;
-import org.hibernate.engine.SessionImplementor;
-import org.hibernate.cfg.Environment;
-
/**
* <tt>binary</tt>: A type that maps an SQL VARBINARY to a Java byte[].
* @author Gavin King
*/
-public class BinaryType extends MutableType implements VersionType, Comparator {
+public class BinaryType extends AbstractBynaryType {
- public void set(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
-
- if ( Environment.useStreamsForBinary() ) {
- st.setBinaryStream( index, new ByteArrayInputStream( (byte[]) value ), ( (byte[]) value ).length );
- }
- else {
- st.setBytes( index, (byte[]) value );
- }
+ protected Object toExternalFormat(byte[] bytes) {
+ return bytes;
}
- public Object get(ResultSet rs, String name) throws HibernateException, SQLException {
-
- if ( Environment.useStreamsForBinary() ) {
-
- InputStream inputStream = rs.getBinaryStream(name);
-
- if (inputStream==null) return null; // is this really necessary?
-
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream(2048);
- byte[] buffer = new byte[2048];
-
- try {
- while (true) {
- int amountRead = inputStream.read(buffer);
- if (amountRead == -1) {
- break;
- }
- outputStream.write(buffer, 0, amountRead);
- }
-
- inputStream.close();
- outputStream.close();
- }
- catch (IOException ioe) {
- throw new HibernateException( "IOException occurred reading a binary value", ioe );
- }
-
- return outputStream.toByteArray();
-
- }
- else {
- return rs.getBytes(name);
- }
+ protected byte[] toInternalFormat(Object bytes) {
+ return (byte[]) bytes;
}
- public int sqlType() {
- return Types.VARBINARY;
- }
-
public Class getReturnedClass() {
return byte[].class;
}
- // VersionType impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // Note : simply returns null for seed() and next() as the only known
- // application of binary types for versioning is for use with the
- // TIMESTAMP datatype supported by Sybase and SQL Server, which
- // are completely db-generated values...
- public Object seed(SessionImplementor session) {
- return null;
- }
-
- public Object next(Object current, SessionImplementor session) {
- return current;
- }
-
- public Comparator getComparator() {
- return this;
- }
-
- public int compare(Object o1, Object o2) {
- return compare( o1, o2, null );
- }
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- public boolean isEqual(Object x, Object y) {
- return x==y || ( x!=null && y!=null && java.util.Arrays.equals( (byte[]) x, (byte[]) y ) );
- }
-
- public int getHashCode(Object x, EntityMode entityMode) {
- byte[] bytes = (byte[]) x;
- int hashCode = 1;
- for ( int j=0; j<bytes.length; j++ ) {
- hashCode = 31 * hashCode + bytes[j];
- }
- return hashCode;
- }
-
- public int compare(Object x, Object y, EntityMode entityMode) {
- byte[] xbytes = (byte[]) x;
- byte[] ybytes = (byte[]) y;
- if ( xbytes.length < ybytes.length ) return -1;
- if ( xbytes.length > ybytes.length ) return 1;
- for ( int i=0; i<xbytes.length; i++ ) {
- if ( xbytes[i] < ybytes[i] ) return -1;
- if ( xbytes[i] > ybytes[i] ) return 1;
- }
- return 0;
- }
-
public String getName() { return "binary"; }
- public String toString(Object val) {
- byte[] bytes = ( byte[] ) val;
- StringBuffer buf = new StringBuffer();
- for ( int i=0; i<bytes.length; i++ ) {
- String hexStr = Integer.toHexString( bytes[i] - Byte.MIN_VALUE );
- if ( hexStr.length()==1 ) buf.append('0');
- buf.append(hexStr);
- }
- return buf.toString();
- }
-
- public Object deepCopyNotNull(Object value) {
- byte[] bytes = (byte[]) value;
- byte[] result = new byte[bytes.length];
- System.arraycopy(bytes, 0, result, 0, bytes.length);
- return result;
- }
-
- public Object fromStringValue(String xml) throws HibernateException {
- if (xml == null)
- return null;
- if (xml.length() % 2 != 0)
- throw new IllegalArgumentException("The string is not a valid xml representation of a binary content.");
- byte[] bytes = new byte[xml.length() / 2];
- for (int i = 0; i < bytes.length; i++) {
- String hexStr = xml.substring(i * 2, (i + 1) * 2);
- bytes[i] = (byte) (Integer.parseInt(hexStr, 16) + Byte.MIN_VALUE);
- }
- return bytes;
- }
}
Added: trunk/Hibernate3/src/org/hibernate/type/CharArrayType.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/type/CharArrayType.java 2006-06-09 17:46:51 UTC (rev 10008)
+++ trunk/Hibernate3/src/org/hibernate/type/CharArrayType.java 2006-06-10 03:24:05 UTC (rev 10009)
@@ -0,0 +1,23 @@
+//$Id: $
+package org.hibernate.type;
+
+/**
+ * put char[] into VARCHAR
+ * @author Emmanuel Bernard
+ */
+public class CharArrayType extends AbstractCharArrayType {
+
+ protected Object toExternalFormat(char[] chars) {
+ return chars;
+ }
+
+ protected char[] toInternalFormat(Object chars) {
+ return (char[]) chars;
+ }
+
+ public Class getReturnedClass() {
+ return char[].class;
+ }
+
+ public String getName() { return "characters"; }
+}
Added: trunk/Hibernate3/src/org/hibernate/type/CharacterArrayType.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/type/CharacterArrayType.java 2006-06-09 17:46:51 UTC (rev 10008)
+++ trunk/Hibernate3/src/org/hibernate/type/CharacterArrayType.java 2006-06-10 03:24:05 UTC (rev 10009)
@@ -0,0 +1,37 @@
+//$Id: $
+package org.hibernate.type;
+
+import org.hibernate.HibernateException;
+
+/**
+ * Bridge Character[] and VARCHAR
+ * @author Emmanuel Bernard
+ */
+public class CharacterArrayType extends AbstractCharArrayType {
+ protected Object toExternalFormat(char[] chars) {
+ if (chars == null) return null;
+ Character[] characters = new Character[chars.length];
+ for (int i = 0 ; i < chars.length ; i++) {
+ characters[i] = new Character( chars[i] );
+ }
+ return characters;
+ }
+
+ protected char[] toInternalFormat(Object value) {
+ if (value == null) return null;
+ Character[] characters = (Character[]) value;
+ char[] chars = new char[characters.length];
+ for (int i = 0 ; i < characters.length ; i++) {
+ if (characters[i] == null)
+ throw new HibernateException("Unable to store an Character[] when one of its element is null");
+ chars[i] = characters[i].charValue();
+ }
+ return chars;
+ }
+
+ public Class getReturnedClass() {
+ return Character[].class;
+ }
+
+ public String getName() { return "wrapper-characters"; }
+}
Modified: trunk/Hibernate3/src/org/hibernate/type/TypeFactory.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/type/TypeFactory.java 2006-06-09 17:46:51 UTC (rev 10008)
+++ trunk/Hibernate3/src/org/hibernate/type/TypeFactory.java 2006-06-10 03:24:05 UTC (rev 10009)
@@ -101,6 +101,12 @@
basics.put( Class.class.getName(), Hibernate.CLASS );
basics.put( byte[].class.getName(), Hibernate.BINARY );
basics.put( "byte[]", Hibernate.BINARY );
+ basics.put( Byte[].class.getName(), Hibernate.WRAPPER_BINARY );
+ basics.put( "Byte[]", Hibernate.WRAPPER_BINARY );
+ basics.put( char[].class.getName(), Hibernate.CHAR_ARRAY );
+ basics.put( "char[]", Hibernate.CHAR_ARRAY );
+ basics.put( Character[].class.getName(), Hibernate.CHARACTER_ARRAY );
+ basics.put( "Character[]", Hibernate.CHARACTER_ARRAY );
basics.put( Blob.class.getName(), Hibernate.BLOB );
basics.put( Clob.class.getName(), Hibernate.CLOB );
basics.put( Serializable.class.getName(), Hibernate.SERIALIZABLE );
Added: trunk/Hibernate3/src/org/hibernate/type/WrapperBinaryType.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/type/WrapperBinaryType.java 2006-06-09 17:46:51 UTC (rev 10008)
+++ trunk/Hibernate3/src/org/hibernate/type/WrapperBinaryType.java 2006-06-10 03:24:05 UTC (rev 10009)
@@ -0,0 +1,41 @@
+//$Id: $
+package org.hibernate.type;
+
+import org.hibernate.HibernateException;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class WrapperBinaryType extends AbstractBynaryType {
+ protected Object toExternalFormat(byte[] bytes) {
+ if (bytes == null) return null;
+ int length = bytes.length;
+ Byte[] result = new Byte[length];
+ for ( int index = 0; index < length ; index++ ) {
+ result[index] = new Byte( bytes[index] );
+ }
+ return result;
+ }
+
+ protected byte[] toInternalFormat(Object val) {
+ if (val == null) return null;
+ Byte[] bytes = (Byte[]) val;
+ int length = bytes.length;
+ byte[] result = new byte[length];
+ for ( int i = 0; i < length ; i++ ) {
+ if (bytes[i] == null)
+ throw new HibernateException("Unable to store an Byte[] when one of its element is null");
+ result[i] = bytes[i].byteValue();
+ }
+ return result;
+ }
+
+ public Class getReturnedClass() {
+ return Byte[].class;
+ }
+
+ public String getName() {
+ //TODO find a decent name before documenting
+ return "wrapper-binary";
+ }
+}
|