147d431f63a66505a645f282416659a9758a91f1cBrett Chabot/* 247d431f63a66505a645f282416659a9758a91f1cBrett Chabot * Copyright 2001-2009 OFFIS, Tammo Freese 347d431f63a66505a645f282416659a9758a91f1cBrett Chabot * 447d431f63a66505a645f282416659a9758a91f1cBrett Chabot * Licensed under the Apache License, Version 2.0 (the "License"); 547d431f63a66505a645f282416659a9758a91f1cBrett Chabot * you may not use this file except in compliance with the License. 647d431f63a66505a645f282416659a9758a91f1cBrett Chabot * You may obtain a copy of the License at 747d431f63a66505a645f282416659a9758a91f1cBrett Chabot * 847d431f63a66505a645f282416659a9758a91f1cBrett Chabot * http://www.apache.org/licenses/LICENSE-2.0 947d431f63a66505a645f282416659a9758a91f1cBrett Chabot * 1047d431f63a66505a645f282416659a9758a91f1cBrett Chabot * Unless required by applicable law or agreed to in writing, software 1147d431f63a66505a645f282416659a9758a91f1cBrett Chabot * distributed under the License is distributed on an "AS IS" BASIS, 1247d431f63a66505a645f282416659a9758a91f1cBrett Chabot * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1347d431f63a66505a645f282416659a9758a91f1cBrett Chabot * See the License for the specific language governing permissions and 1447d431f63a66505a645f282416659a9758a91f1cBrett Chabot * limitations under the License. 1547d431f63a66505a645f282416659a9758a91f1cBrett Chabot */ 1647d431f63a66505a645f282416659a9758a91f1cBrett Chabotpackage org.easymock.internal; 1747d431f63a66505a645f282416659a9758a91f1cBrett Chabot 1847d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport static java.lang.Character.*; 1947d431f63a66505a645f282416659a9758a91f1cBrett Chabot 2047d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport java.io.IOException; 2147d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport java.io.Serializable; 2247d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport java.lang.reflect.Array; 2347d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport java.lang.reflect.Method; 2447d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport java.util.ArrayList; 2547d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport java.util.Collection; 2647d431f63a66505a645f282416659a9758a91f1cBrett Chabot 2747d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport org.easymock.internal.matchers.Captures; 2847d431f63a66505a645f282416659a9758a91f1cBrett Chabot 2947d431f63a66505a645f282416659a9758a91f1cBrett Chabotpublic class Invocation implements Serializable { 3047d431f63a66505a645f282416659a9758a91f1cBrett Chabot 3147d431f63a66505a645f282416659a9758a91f1cBrett Chabot private static final long serialVersionUID = 1604995470419943411L; 3247d431f63a66505a645f282416659a9758a91f1cBrett Chabot 3347d431f63a66505a645f282416659a9758a91f1cBrett Chabot private final Object mock; 3447d431f63a66505a645f282416659a9758a91f1cBrett Chabot 3547d431f63a66505a645f282416659a9758a91f1cBrett Chabot private transient Method method; 3647d431f63a66505a645f282416659a9758a91f1cBrett Chabot 3747d431f63a66505a645f282416659a9758a91f1cBrett Chabot private final Object[] arguments; 3847d431f63a66505a645f282416659a9758a91f1cBrett Chabot 3947d431f63a66505a645f282416659a9758a91f1cBrett Chabot private final Collection<Captures<?>> currentCaptures = new ArrayList<Captures<?>>( 4047d431f63a66505a645f282416659a9758a91f1cBrett Chabot 0); 4147d431f63a66505a645f282416659a9758a91f1cBrett Chabot 4247d431f63a66505a645f282416659a9758a91f1cBrett Chabot public Invocation(Object mock, Method method, Object[] args) { 4347d431f63a66505a645f282416659a9758a91f1cBrett Chabot this.mock = mock; 4447d431f63a66505a645f282416659a9758a91f1cBrett Chabot this.method = method; 4547d431f63a66505a645f282416659a9758a91f1cBrett Chabot this.arguments = expandVarArgs(method.isVarArgs(), args); 4647d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 4747d431f63a66505a645f282416659a9758a91f1cBrett Chabot 4847d431f63a66505a645f282416659a9758a91f1cBrett Chabot private static Object[] expandVarArgs(final boolean isVarArgs, 4947d431f63a66505a645f282416659a9758a91f1cBrett Chabot final Object[] args) { 5047d431f63a66505a645f282416659a9758a91f1cBrett Chabot if (!isVarArgs) { 5147d431f63a66505a645f282416659a9758a91f1cBrett Chabot return args == null ? new Object[0] : args; 5247d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 5347d431f63a66505a645f282416659a9758a91f1cBrett Chabot if (args[args.length - 1] == null) { 5447d431f63a66505a645f282416659a9758a91f1cBrett Chabot return args; 5547d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 5647d431f63a66505a645f282416659a9758a91f1cBrett Chabot Object[] varArgs = createObjectArray(args[args.length - 1]); 5747d431f63a66505a645f282416659a9758a91f1cBrett Chabot final int nonVarArgsCount = args.length - 1; 5847d431f63a66505a645f282416659a9758a91f1cBrett Chabot final int varArgsCount = varArgs.length; 5947d431f63a66505a645f282416659a9758a91f1cBrett Chabot Object[] newArgs = new Object[nonVarArgsCount + varArgsCount]; 6047d431f63a66505a645f282416659a9758a91f1cBrett Chabot System.arraycopy(args, 0, newArgs, 0, nonVarArgsCount); 6147d431f63a66505a645f282416659a9758a91f1cBrett Chabot System.arraycopy(varArgs, 0, newArgs, nonVarArgsCount, varArgsCount); 6247d431f63a66505a645f282416659a9758a91f1cBrett Chabot return newArgs; 6347d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 6447d431f63a66505a645f282416659a9758a91f1cBrett Chabot 6547d431f63a66505a645f282416659a9758a91f1cBrett Chabot private static Object[] createObjectArray(Object array) { 6647d431f63a66505a645f282416659a9758a91f1cBrett Chabot if (array instanceof Object[]) { 6747d431f63a66505a645f282416659a9758a91f1cBrett Chabot return (Object[]) array; 6847d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 6947d431f63a66505a645f282416659a9758a91f1cBrett Chabot Object[] result = new Object[Array.getLength(array)]; 7047d431f63a66505a645f282416659a9758a91f1cBrett Chabot for (int i = 0; i < Array.getLength(array); i++) { 7147d431f63a66505a645f282416659a9758a91f1cBrett Chabot result[i] = Array.get(array, i); 7247d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 7347d431f63a66505a645f282416659a9758a91f1cBrett Chabot return result; 7447d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 7547d431f63a66505a645f282416659a9758a91f1cBrett Chabot 7647d431f63a66505a645f282416659a9758a91f1cBrett Chabot public Object getMock() { 7747d431f63a66505a645f282416659a9758a91f1cBrett Chabot return mock; 7847d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 7947d431f63a66505a645f282416659a9758a91f1cBrett Chabot 8047d431f63a66505a645f282416659a9758a91f1cBrett Chabot public Method getMethod() { 8147d431f63a66505a645f282416659a9758a91f1cBrett Chabot return method; 8247d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 8347d431f63a66505a645f282416659a9758a91f1cBrett Chabot 8447d431f63a66505a645f282416659a9758a91f1cBrett Chabot public Object[] getArguments() { 8547d431f63a66505a645f282416659a9758a91f1cBrett Chabot return arguments; 8647d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 8747d431f63a66505a645f282416659a9758a91f1cBrett Chabot 8847d431f63a66505a645f282416659a9758a91f1cBrett Chabot @Override 8947d431f63a66505a645f282416659a9758a91f1cBrett Chabot public boolean equals(Object o) { 9047d431f63a66505a645f282416659a9758a91f1cBrett Chabot if (o == null || !o.getClass().equals(this.getClass())) 9147d431f63a66505a645f282416659a9758a91f1cBrett Chabot return false; 9247d431f63a66505a645f282416659a9758a91f1cBrett Chabot 9347d431f63a66505a645f282416659a9758a91f1cBrett Chabot Invocation other = (Invocation) o; 9447d431f63a66505a645f282416659a9758a91f1cBrett Chabot 9547d431f63a66505a645f282416659a9758a91f1cBrett Chabot return this.mock.equals(other.mock) && this.method.equals(other.method) 9647d431f63a66505a645f282416659a9758a91f1cBrett Chabot && this.equalArguments(other.arguments); 9747d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 9847d431f63a66505a645f282416659a9758a91f1cBrett Chabot 9947d431f63a66505a645f282416659a9758a91f1cBrett Chabot @Override 10047d431f63a66505a645f282416659a9758a91f1cBrett Chabot public int hashCode() { 10147d431f63a66505a645f282416659a9758a91f1cBrett Chabot throw new UnsupportedOperationException("hashCode() is not implemented"); 10247d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 10347d431f63a66505a645f282416659a9758a91f1cBrett Chabot 10447d431f63a66505a645f282416659a9758a91f1cBrett Chabot private boolean equalArguments(Object[] arguments) { 10547d431f63a66505a645f282416659a9758a91f1cBrett Chabot if (this.arguments.length != arguments.length) { 10647d431f63a66505a645f282416659a9758a91f1cBrett Chabot return false; 10747d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 10847d431f63a66505a645f282416659a9758a91f1cBrett Chabot for (int i = 0; i < this.arguments.length; i++) { 10947d431f63a66505a645f282416659a9758a91f1cBrett Chabot Object myArgument = this.arguments[i]; 11047d431f63a66505a645f282416659a9758a91f1cBrett Chabot Object otherArgument = arguments[i]; 11147d431f63a66505a645f282416659a9758a91f1cBrett Chabot 11247d431f63a66505a645f282416659a9758a91f1cBrett Chabot if (isPrimitiveParameter(i)) { 11347d431f63a66505a645f282416659a9758a91f1cBrett Chabot if (!myArgument.equals(otherArgument)) { 11447d431f63a66505a645f282416659a9758a91f1cBrett Chabot return false; 11547d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 11647d431f63a66505a645f282416659a9758a91f1cBrett Chabot } else { 11747d431f63a66505a645f282416659a9758a91f1cBrett Chabot if (myArgument != otherArgument) { 11847d431f63a66505a645f282416659a9758a91f1cBrett Chabot return false; 11947d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 12047d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 12147d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 12247d431f63a66505a645f282416659a9758a91f1cBrett Chabot return true; 12347d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 12447d431f63a66505a645f282416659a9758a91f1cBrett Chabot 12547d431f63a66505a645f282416659a9758a91f1cBrett Chabot private boolean isPrimitiveParameter(int parameterPosition) { 12647d431f63a66505a645f282416659a9758a91f1cBrett Chabot Class<?>[] parameterTypes = method.getParameterTypes(); 12747d431f63a66505a645f282416659a9758a91f1cBrett Chabot if (method.isVarArgs()) { 12847d431f63a66505a645f282416659a9758a91f1cBrett Chabot parameterPosition = Math.min(parameterPosition, 12947d431f63a66505a645f282416659a9758a91f1cBrett Chabot parameterTypes.length - 1); 13047d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 13147d431f63a66505a645f282416659a9758a91f1cBrett Chabot return parameterTypes[parameterPosition].isPrimitive(); 13247d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 13347d431f63a66505a645f282416659a9758a91f1cBrett Chabot 13447d431f63a66505a645f282416659a9758a91f1cBrett Chabot @SuppressWarnings("deprecation") 13547d431f63a66505a645f282416659a9758a91f1cBrett Chabot public boolean matches(Invocation actual, org.easymock.ArgumentsMatcher matcher) { 13647d431f63a66505a645f282416659a9758a91f1cBrett Chabot return this.mock.equals(actual.mock) 13747d431f63a66505a645f282416659a9758a91f1cBrett Chabot && this.method.equals(actual.method) 13847d431f63a66505a645f282416659a9758a91f1cBrett Chabot && matcher.matches(this.arguments, actual.arguments); 13947d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 14047d431f63a66505a645f282416659a9758a91f1cBrett Chabot 14147d431f63a66505a645f282416659a9758a91f1cBrett Chabot @SuppressWarnings("deprecation") 14247d431f63a66505a645f282416659a9758a91f1cBrett Chabot public String toString(org.easymock.ArgumentsMatcher matcher) { 14347d431f63a66505a645f282416659a9758a91f1cBrett Chabot return getMockAndMethodName() + "(" + matcher.toString(arguments) + ")"; 14447d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 14547d431f63a66505a645f282416659a9758a91f1cBrett Chabot 14647d431f63a66505a645f282416659a9758a91f1cBrett Chabot public String getMockAndMethodName() { 14747d431f63a66505a645f282416659a9758a91f1cBrett Chabot String mockName = mock.toString(); 14847d431f63a66505a645f282416659a9758a91f1cBrett Chabot String methodName = method.getName(); 14947d431f63a66505a645f282416659a9758a91f1cBrett Chabot if (toStringIsDefined(mock) && isJavaIdentifier(mockName)) { 15047d431f63a66505a645f282416659a9758a91f1cBrett Chabot return mockName + "." + methodName; 15147d431f63a66505a645f282416659a9758a91f1cBrett Chabot } else { 15247d431f63a66505a645f282416659a9758a91f1cBrett Chabot return methodName; 15347d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 15447d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 15547d431f63a66505a645f282416659a9758a91f1cBrett Chabot 15647d431f63a66505a645f282416659a9758a91f1cBrett Chabot public void addCapture(Captures<Object> capture, Object value) { 15747d431f63a66505a645f282416659a9758a91f1cBrett Chabot capture.setPotentialValue(value); 15847d431f63a66505a645f282416659a9758a91f1cBrett Chabot currentCaptures.add(capture); 15947d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 16047d431f63a66505a645f282416659a9758a91f1cBrett Chabot 16147d431f63a66505a645f282416659a9758a91f1cBrett Chabot public void validateCaptures() { 16247d431f63a66505a645f282416659a9758a91f1cBrett Chabot for (Captures<?> c : currentCaptures) { 16347d431f63a66505a645f282416659a9758a91f1cBrett Chabot c.validateCapture(); 16447d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 16547d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 16647d431f63a66505a645f282416659a9758a91f1cBrett Chabot 16747d431f63a66505a645f282416659a9758a91f1cBrett Chabot public void clearCaptures() { 16847d431f63a66505a645f282416659a9758a91f1cBrett Chabot for (Captures<?> c : currentCaptures) { 16947d431f63a66505a645f282416659a9758a91f1cBrett Chabot c.setPotentialValue(null); 17047d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 17147d431f63a66505a645f282416659a9758a91f1cBrett Chabot currentCaptures.clear(); 17247d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 17347d431f63a66505a645f282416659a9758a91f1cBrett Chabot 17447d431f63a66505a645f282416659a9758a91f1cBrett Chabot private boolean toStringIsDefined(Object o) { 17547d431f63a66505a645f282416659a9758a91f1cBrett Chabot try { 17647d431f63a66505a645f282416659a9758a91f1cBrett Chabot o.getClass().getDeclaredMethod("toString", (Class[]) null) 17747d431f63a66505a645f282416659a9758a91f1cBrett Chabot .getModifiers(); 17847d431f63a66505a645f282416659a9758a91f1cBrett Chabot return true; 17947d431f63a66505a645f282416659a9758a91f1cBrett Chabot } catch (SecurityException ignored) { 18047d431f63a66505a645f282416659a9758a91f1cBrett Chabot // ///CLOVER:OFF 18147d431f63a66505a645f282416659a9758a91f1cBrett Chabot return false; 18247d431f63a66505a645f282416659a9758a91f1cBrett Chabot // ///CLOVER:ON 18347d431f63a66505a645f282416659a9758a91f1cBrett Chabot } catch (NoSuchMethodException shouldNeverHappen) { 18447d431f63a66505a645f282416659a9758a91f1cBrett Chabot // ///CLOVER:OFF 18547d431f63a66505a645f282416659a9758a91f1cBrett Chabot throw new RuntimeException("The toString() method could not be found!"); 18647d431f63a66505a645f282416659a9758a91f1cBrett Chabot // ///CLOVER:ON 18747d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 18847d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 18947d431f63a66505a645f282416659a9758a91f1cBrett Chabot 19047d431f63a66505a645f282416659a9758a91f1cBrett Chabot public static boolean isJavaIdentifier(String mockName) { 19147d431f63a66505a645f282416659a9758a91f1cBrett Chabot if (mockName.length() == 0 || mockName.indexOf(' ') > -1 19247d431f63a66505a645f282416659a9758a91f1cBrett Chabot || !Character.isJavaIdentifierStart(mockName.charAt(0))) { 19347d431f63a66505a645f282416659a9758a91f1cBrett Chabot return false; 19447d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 19547d431f63a66505a645f282416659a9758a91f1cBrett Chabot for (char c : mockName.substring(1).toCharArray()) { 19647d431f63a66505a645f282416659a9758a91f1cBrett Chabot if (!isJavaIdentifierPart(c)) { 19747d431f63a66505a645f282416659a9758a91f1cBrett Chabot return false; 19847d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 19947d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 20047d431f63a66505a645f282416659a9758a91f1cBrett Chabot return true; 20147d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 20247d431f63a66505a645f282416659a9758a91f1cBrett Chabot 20347d431f63a66505a645f282416659a9758a91f1cBrett Chabot private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { 20447d431f63a66505a645f282416659a9758a91f1cBrett Chabot stream.defaultReadObject(); 20547d431f63a66505a645f282416659a9758a91f1cBrett Chabot try { 20647d431f63a66505a645f282416659a9758a91f1cBrett Chabot method = ((MethodSerializationWrapper) stream.readObject()).getMethod(); 20747d431f63a66505a645f282416659a9758a91f1cBrett Chabot } catch (NoSuchMethodException e) { 20847d431f63a66505a645f282416659a9758a91f1cBrett Chabot // ///CLOVER:OFF 20947d431f63a66505a645f282416659a9758a91f1cBrett Chabot throw new IOException(e.toString()); 21047d431f63a66505a645f282416659a9758a91f1cBrett Chabot // ///CLOVER:ON 21147d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 21247d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 21347d431f63a66505a645f282416659a9758a91f1cBrett Chabot 21447d431f63a66505a645f282416659a9758a91f1cBrett Chabot private void writeObject(java.io.ObjectOutputStream stream) throws IOException { 21547d431f63a66505a645f282416659a9758a91f1cBrett Chabot stream.defaultWriteObject(); 21647d431f63a66505a645f282416659a9758a91f1cBrett Chabot stream.writeObject(new MethodSerializationWrapper(method)); 21747d431f63a66505a645f282416659a9758a91f1cBrett Chabot } 21847d431f63a66505a645f282416659a9758a91f1cBrett Chabot} 219