View Javadoc

1   /*
2    *
3    * The DbUnit Database Testing Framework
4    * Copyright (C)2002-2004, DbUnit.org
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 2.1 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   *
20   */
21  
22  package org.dbunit.dataset.datatype;
23  
24  import java.io.BufferedInputStream;
25  import java.io.ByteArrayOutputStream;
26  import java.io.File;
27  import java.io.FileInputStream;
28  import java.io.FileNotFoundException;
29  import java.io.IOException;
30  import java.io.InputStream;
31  import java.net.MalformedURLException;
32  import java.net.URL;
33  import java.sql.Blob;
34  import java.sql.PreparedStatement;
35  import java.sql.ResultSet;
36  import java.sql.SQLException;
37  
38  import org.dbunit.dataset.ITable;
39  import org.dbunit.util.Base64;
40  import org.slf4j.Logger;
41  import org.slf4j.LoggerFactory;
42  
43  /**
44   * @author Manuel Laflamme
45   * @author Last changed by: $Author: gommma $
46   * @version $Revision: 1179 $ $Date: 2010-03-25 23:09:07 +0100 (gio, 25 mar 2010) $
47   * @since 1.0 (Mar 20, 2002)
48   */
49  public class BytesDataType extends AbstractDataType
50  {
51  
52      /**
53       * Logger for this class
54       */
55      private static final Logger logger = LoggerFactory.getLogger(BytesDataType.class);
56  
57      private static final int MAX_URI_LENGTH = 256;
58  
59      BytesDataType(String name, int sqlType)
60      {
61          super(name, sqlType, byte[].class, false);
62      }
63  
64      private byte[] toByteArray(InputStream in, int length) throws IOException
65      {
66          if (logger.isDebugEnabled())
67  		{
68  			logger.debug("toByteArray(in={}, length={}) - start", in, Integer.toString(length));
69  		}
70  
71          ByteArrayOutputStream out = new ByteArrayOutputStream(length);
72          in = new BufferedInputStream(in);
73          int i = in.read();
74          while (i != -1)
75          {
76              out.write(i);
77              i = in.read();
78          }
79          return out.toByteArray();
80      }
81  
82      ////////////////////////////////////////////////////////////////////////////
83      // DataType class
84  
85      /**
86       * Casts the given value into a byte[] using different strategies. Note
87       * that this might sometimes result in undesired behavior when character
88       * data (Strings) are used.
89       * 
90       * @see org.dbunit.dataset.datatype.DataType#typeCast(java.lang.Object)
91       */
92      public Object typeCast(Object value) throws TypeCastException
93      {
94          logger.debug("typeCast(value={}) - start", value);
95  
96          if (value == null || value == ITable.NO_VALUE)
97          {
98              return null;
99          }
100 
101         if (value instanceof byte[])
102         {
103             return value;
104         }
105 
106         if (value instanceof String)
107         {
108             String stringValue = (String)value;
109 
110             // Assume not an uri if length greater than max uri length
111             if (stringValue.length() == 0 || stringValue.length() > MAX_URI_LENGTH)
112             {
113             	logger.debug("Assuming given string to be Base64 and not a URI");
114                 return Base64.decode((String)value);
115             }
116 
117             try
118             {
119             	logger.debug("Assuming given string to be a URI");
120                 try
121                 {
122                     // Try value as URL
123                     URL url = new URL(stringValue);
124                     return toByteArray(url.openStream(), 0);
125                 }
126                 catch (MalformedURLException e1)
127                 {
128                 	logger.debug("Given string is not a valid URI - trying to resolve it as file...");
129                     try
130                     {
131                         // Not an URL, try as file name
132                         File file = new File(stringValue);
133                         return toByteArray(new FileInputStream(file), (int)file.length());
134                     }
135                     catch (FileNotFoundException e2)
136                     {
137                         logger.debug("Assuming given string to be Base64 and not a URI or File");
138                         // Not a file name either
139                         return Base64.decode(stringValue);
140                     }
141                 }
142             }
143             catch (IOException e)
144             {
145                 throw new TypeCastException(value, this, e);
146             }
147         }
148 
149         if (value instanceof Blob)
150         {
151             try
152             {
153                 Blob blobValue = (Blob)value;
154                 if (blobValue.length() == 0) {
155                     return null;
156                 }
157                 return blobValue.getBytes(1, (int)blobValue.length());
158             }
159             catch (SQLException e)
160             {
161                 throw new TypeCastException(value, this, e);
162             }
163         }
164 
165         if (value instanceof URL)
166         {
167             try
168             {
169                 return toByteArray(((URL)value).openStream(), 0);
170             }
171             catch (IOException e)
172             {
173                 throw new TypeCastException(value, this, e);
174             }
175         }
176 
177         if (value instanceof File)
178         {
179             try
180             {
181                 File file = (File)value;
182                 return toByteArray(new FileInputStream(file), (int)file.length());
183             }
184             catch (IOException e)
185             {
186                 throw new TypeCastException(value, this, e);
187             }
188         }
189 
190         throw new TypeCastException(value, this);
191     }
192 
193 
194     protected int compareNonNulls(Object value1, Object value2) throws TypeCastException
195     {
196         logger.debug("compareNonNulls(value1={}, value2={}) - start", value1, value2);
197 
198         try
199         {
200             byte[] value1cast = (byte[])typeCast(value1);
201             byte[] value2cast = (byte[])typeCast(value2);
202     
203             return compare(value1cast, value2cast);
204         }
205         catch (ClassCastException e)
206         {
207             throw new TypeCastException(e);
208         }
209     }
210 
211     public int compare(byte[] v1, byte[] v2) throws TypeCastException
212     {
213         if (logger.isDebugEnabled())
214 		{
215 			logger.debug("compare(v1={}, v2={}) - start", v1, v2);
216 		}
217 
218         int len1 = v1.length;
219         int len2 = v2.length;
220         int n = Math.min(len1, len2);
221         int i = 0;
222         int j = 0;
223 
224         if (i == j)
225         {
226             int k = i;
227             int lim = n + i;
228             while (k < lim)
229             {
230                 byte c1 = v1[k];
231                 byte c2 = v2[k];
232                 if (c1 != c2)
233                 {
234                     return c1 - c2;
235                 }
236                 k++;
237             }
238         }
239         else
240         {
241             while (n-- != 0)
242             {
243                 byte c1 = v1[i++];
244                 byte c2 = v2[j++];
245                 if (c1 != c2)
246                 {
247                     return c1 - c2;
248                 }
249             }
250         }
251         return len1 - len2;
252     }
253 
254     public Object getSqlValue(int column, ResultSet resultSet)
255             throws SQLException, TypeCastException
256     {
257     	if(logger.isDebugEnabled())
258     		logger.debug("getSqlValue(column={}, resultSet={}) - start", new Integer(column), resultSet);
259 
260         byte[] value = resultSet.getBytes(column);
261         if (value == null || resultSet.wasNull())
262         {
263             return null;
264         }
265         return value;
266     }
267 
268     public void setSqlValue(Object value, int column, PreparedStatement statement)
269             throws SQLException, TypeCastException
270     {
271     	if (logger.isDebugEnabled()) 
272     	{
273     		logger.debug("setSqlValue(value={}, column={}, statement={}) - start",
274         		new Object[]{value, new Integer(column), statement} );
275     	}
276 
277         super.setSqlValue(value, column, statement);
278     }
279 
280 }