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