001 package com.mockrunner.jdbc; 002 003 import java.io.InputStream; 004 import java.io.Reader; 005 import java.sql.SQLException; 006 import java.util.Arrays; 007 008 import com.mockrunner.mock.jdbc.MockArray; 009 import com.mockrunner.mock.jdbc.MockBlob; 010 import com.mockrunner.mock.jdbc.MockClob; 011 import com.mockrunner.mock.jdbc.MockRef; 012 import com.mockrunner.mock.jdbc.MockStruct; 013 import com.mockrunner.util.common.ArrayUtil; 014 import com.mockrunner.util.common.MethodUtil; 015 import com.mockrunner.util.common.StreamUtil; 016 017 /** 018 * Util class for <code>PreparedStatement</code> and <code>ResultSet</code> 019 * parameters. 020 */ 021 public class ParameterUtil 022 { 023 /** 024 * Copies a parameter of a <code>PreparedStatement</code>, 025 * <code>CallableStatement</code> or <code>ResultSet</code>. 026 * <code>InputStream</code> objects, <code>Reader</code> objects 027 * and arrays are copied into new allocated streams resp. arrays. 028 * All other objects are cloned by calling the clone method. 029 * If the object is not cloneable, it is returned unchanged. 030 * @param source the parameter to copy 031 * @return a copy of the parameter 032 */ 033 public static Object copyParameter(Object source) 034 { 035 if(null == source) return null; 036 if(source.getClass().isArray()) 037 { 038 return ArrayUtil.copyArray(source); 039 } 040 if(source instanceof InputStream) 041 { 042 return StreamUtil.copyStream((InputStream)source); 043 } 044 if(source instanceof Reader) 045 { 046 return StreamUtil.copyReader((Reader)source); 047 } 048 if(source instanceof Cloneable) 049 { 050 try 051 { 052 return MethodUtil.invoke(source, "clone"); 053 } 054 catch(Exception exc) 055 { 056 return source; 057 } 058 } 059 return source; 060 } 061 062 /** 063 * Compares two parameters of a <code>PreparedStatement</code> or 064 * <code>CallableStatement</code>. You can use it to compare 065 * parameters of a <code>ResultSet</code>. It is used by 066 * {@link com.mockrunner.jdbc.PreparedStatementResultSetHandler} 067 * for comparing parameters specified in the <code>prepare</code> 068 * methods. 069 * Since the parameters can be of the type <code>byte[]</code>, 070 * <code>InputStream</code>, <code>Reader</code>, <code>Ref</code>, 071 * <code>Array</code>, <code>Blob</code>, <code>Clob</code> or 072 * <code>Struct</code> this method can handle these types of objects. 073 * All other objects are compared using the <code>equals</code> method. 074 * @param source the first parameter 075 * @param target the second parameter 076 * @return <code>true</code> if <i>source</i> is equal to <i>target</i>, 077 * <code>false</code> otherwise 078 */ 079 public static boolean compareParameter(Object source, Object target) 080 { 081 if(null == source && null == target) return true; 082 if(null == source || null == target) return false; 083 if(source instanceof byte[] && target instanceof byte[]) 084 { 085 return Arrays.equals((byte[])source, (byte[])target); 086 } 087 if(source instanceof InputStream && target instanceof InputStream) 088 { 089 return StreamUtil.compareStreams((InputStream)source, (InputStream)target); 090 } 091 if(source instanceof Reader && target instanceof Reader) 092 { 093 return StreamUtil.compareReaders((Reader)source, (Reader)target); 094 } 095 if(source instanceof MockRef && target instanceof MockRef) 096 { 097 return compareRef(source, target); 098 } 099 if(source instanceof MockArray && target instanceof MockArray) 100 { 101 return compareArray(source, target); 102 } 103 if(source instanceof MockBlob && target instanceof MockBlob) 104 { 105 return compareBlob(source, target); 106 } 107 if(source instanceof MockClob && target instanceof MockClob) 108 { 109 return compareClob(source, target); 110 } 111 if(source instanceof MockStruct && target instanceof MockStruct) 112 { 113 return compareStruct(source, target); 114 } 115 return source.equals(target); 116 } 117 118 private static boolean compareClob(Object source, Object target) 119 { 120 try 121 { 122 String sourceString = ((MockClob)source).getSubString(1, (int)((MockClob)source).length()); 123 String targetString = ((MockClob)target).getSubString(1, (int)((MockClob)target).length()); 124 return sourceString.equals(targetString); 125 } 126 catch(SQLException exc) 127 { 128 return false; 129 } 130 } 131 132 private static boolean compareBlob(Object source, Object target) 133 { 134 try 135 { 136 byte[] sourceArray = ((MockBlob)source).getBytes(1, (int)((MockBlob)source).length()); 137 byte[] targetArray = ((MockBlob)target).getBytes(1, (int)((MockBlob)target).length()); 138 return Arrays.equals(sourceArray, targetArray); 139 } 140 catch(SQLException exc) 141 { 142 return false; 143 } 144 } 145 146 private static boolean compareArray(Object source, Object target) 147 { 148 try 149 { 150 Object[] sourceArray = ArrayUtil.convertToObjectArray(((MockArray)source).getArray()); 151 Object[] targetArray = ArrayUtil.convertToObjectArray(((MockArray)target).getArray()); 152 return Arrays.equals(sourceArray, targetArray); 153 } 154 catch(SQLException exc) 155 { 156 return false; 157 } 158 } 159 160 private static boolean compareRef(Object source, Object target) 161 { 162 try 163 { 164 return ((MockRef)source).getObject().equals(((MockRef)target).getObject()); 165 } 166 catch(SQLException exc) 167 { 168 return false; 169 } 170 } 171 172 private static boolean compareStruct(Object source, Object target) 173 { 174 try 175 { 176 String sourceName = ((MockStruct)source).getSQLTypeName(); 177 String targetName = ((MockStruct)target).getSQLTypeName(); 178 Object[] sourceArray = ((MockStruct)source).getAttributes(); 179 Object[] targetArray = ((MockStruct)target).getAttributes(); 180 return (sourceName.equals(targetName)) && (Arrays.equals(sourceArray, targetArray)); 181 } 182 catch(SQLException exc) 183 { 184 return false; 185 } 186 } 187 } 188