001 package com.mockrunner.jdbc; 002 003 import java.io.InputStream; 004 import java.io.Reader; 005 import java.util.Arrays; 006 007 import com.mockrunner.mock.jdbc.MockResultSet; 008 import com.mockrunner.util.common.ArrayUtil; 009 import com.mockrunner.util.common.MethodUtil; 010 import com.mockrunner.util.common.StreamUtil; 011 012 /** 013 * Util class for <code>PreparedStatement</code> and <code>ResultSet</code> 014 * parameters. 015 */ 016 public class ParameterUtil 017 { 018 /** 019 * Copies a parameter of a <code>PreparedStatement</code>, 020 * <code>CallableStatement</code> or a <code>ResultSet</code> value. 021 * <code>InputStream</code> objects, <code>Reader</code> objects 022 * and arrays are copied into new allocated streams or arrays. 023 * All other objects are cloned by calling the clone method. 024 * If the object is not cloneable, it is returned unchanged. 025 * @param source the parameter to copy 026 * @return a copy of the parameter 027 */ 028 public static Object copyParameter(Object source) 029 { 030 if(null == source) return null; 031 if(source.getClass().isArray()) 032 { 033 return ArrayUtil.copyArray(source); 034 } 035 if(source instanceof InputStream) 036 { 037 return StreamUtil.copyStream((InputStream)source); 038 } 039 if(source instanceof Reader) 040 { 041 return StreamUtil.copyReader((Reader)source); 042 } 043 if(source instanceof Cloneable) 044 { 045 try 046 { 047 return MethodUtil.invoke(source, "clone"); 048 } 049 catch(Exception exc) 050 { 051 return source; 052 } 053 } 054 return source; 055 } 056 057 /** 058 * Compares two parameters of a <code>PreparedStatement</code> or 059 * <code>CallableStatement</code>. Can also be used to compare 060 * values of a <code>ResultSet</code>. It is used by 061 * {@link com.mockrunner.jdbc.PreparedStatementResultSetHandler} 062 * for comparing parameters specified in the <code>prepare</code> 063 * methods. 064 * Since the parameters can be of the type <code>byte[]</code>, 065 * <code>InputStream</code> and <code>Reader</code> this method handles 066 * these types of objects. All other objects are compared using the 067 * <code>equals</code> method. The mock versions of <code>Ref</code>, 068 * <code>Array</code>, <code>Blob</code>, <code>Clob</code> and 069 * <code>Struct</code> all provide a suitable <code>equals</code> 070 * implementation. 071 * @param source the first parameter 072 * @param target the second parameter 073 * @return <code>true</code> if <i>source</i> is equal to <i>target</i>, 074 * <code>false</code> otherwise 075 */ 076 public static boolean compareParameter(Object source, Object target) 077 { 078 if(null == source && null == target) return true; 079 if(null == source || null == target) return false; 080 if(source instanceof byte[] && target instanceof byte[]) 081 { 082 return Arrays.equals((byte[])source, (byte[])target); 083 } 084 if(source instanceof InputStream && target instanceof InputStream) 085 { 086 return StreamUtil.compareStreams((InputStream)source, (InputStream)target); 087 } 088 if(source instanceof Reader && target instanceof Reader) 089 { 090 return StreamUtil.compareReaders((Reader)source, (Reader)target); 091 } 092 if(source instanceof MockResultSet && target instanceof MockResultSet) 093 { 094 return ((MockResultSet)source).isEqual((MockResultSet)target); 095 } 096 return source.equals(target); 097 } 098 } 099