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>,
069 * <code>Struct</code> etc. 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