/* | |
* Copyright 2001-2009 OFFIS, Tammo Freese | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package org.easymock.internal; | |
import static java.lang.Character.*; | |
import java.io.IOException; | |
import java.io.Serializable; | |
import java.lang.reflect.Array; | |
import java.lang.reflect.Method; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import org.easymock.internal.matchers.Captures; | |
public class Invocation implements Serializable { | |
private static final long serialVersionUID = 1604995470419943411L; | |
private final Object mock; | |
private transient Method method; | |
private final Object[] arguments; | |
private final Collection<Captures<?>> currentCaptures = new ArrayList<Captures<?>>( | |
0); | |
public Invocation(Object mock, Method method, Object[] args) { | |
this.mock = mock; | |
this.method = method; | |
this.arguments = expandVarArgs(method.isVarArgs(), args); | |
} | |
private static Object[] expandVarArgs(final boolean isVarArgs, | |
final Object[] args) { | |
if (!isVarArgs) { | |
return args == null ? new Object[0] : args; | |
} | |
if (args[args.length - 1] == null) { | |
return args; | |
} | |
Object[] varArgs = createObjectArray(args[args.length - 1]); | |
final int nonVarArgsCount = args.length - 1; | |
final int varArgsCount = varArgs.length; | |
Object[] newArgs = new Object[nonVarArgsCount + varArgsCount]; | |
System.arraycopy(args, 0, newArgs, 0, nonVarArgsCount); | |
System.arraycopy(varArgs, 0, newArgs, nonVarArgsCount, varArgsCount); | |
return newArgs; | |
} | |
private static Object[] createObjectArray(Object array) { | |
if (array instanceof Object[]) { | |
return (Object[]) array; | |
} | |
Object[] result = new Object[Array.getLength(array)]; | |
for (int i = 0; i < Array.getLength(array); i++) { | |
result[i] = Array.get(array, i); | |
} | |
return result; | |
} | |
public Object getMock() { | |
return mock; | |
} | |
public Method getMethod() { | |
return method; | |
} | |
public Object[] getArguments() { | |
return arguments; | |
} | |
@Override | |
public boolean equals(Object o) { | |
if (o == null || !o.getClass().equals(this.getClass())) | |
return false; | |
Invocation other = (Invocation) o; | |
return this.mock.equals(other.mock) && this.method.equals(other.method) | |
&& this.equalArguments(other.arguments); | |
} | |
@Override | |
public int hashCode() { | |
throw new UnsupportedOperationException("hashCode() is not implemented"); | |
} | |
private boolean equalArguments(Object[] arguments) { | |
if (this.arguments.length != arguments.length) { | |
return false; | |
} | |
for (int i = 0; i < this.arguments.length; i++) { | |
Object myArgument = this.arguments[i]; | |
Object otherArgument = arguments[i]; | |
if (isPrimitiveParameter(i)) { | |
if (!myArgument.equals(otherArgument)) { | |
return false; | |
} | |
} else { | |
if (myArgument != otherArgument) { | |
return false; | |
} | |
} | |
} | |
return true; | |
} | |
private boolean isPrimitiveParameter(int parameterPosition) { | |
Class<?>[] parameterTypes = method.getParameterTypes(); | |
if (method.isVarArgs()) { | |
parameterPosition = Math.min(parameterPosition, | |
parameterTypes.length - 1); | |
} | |
return parameterTypes[parameterPosition].isPrimitive(); | |
} | |
@SuppressWarnings("deprecation") | |
public boolean matches(Invocation actual, org.easymock.ArgumentsMatcher matcher) { | |
return this.mock.equals(actual.mock) | |
&& this.method.equals(actual.method) | |
&& matcher.matches(this.arguments, actual.arguments); | |
} | |
@SuppressWarnings("deprecation") | |
public String toString(org.easymock.ArgumentsMatcher matcher) { | |
return getMockAndMethodName() + "(" + matcher.toString(arguments) + ")"; | |
} | |
public String getMockAndMethodName() { | |
String mockName = mock.toString(); | |
String methodName = method.getName(); | |
if (toStringIsDefined(mock) && isJavaIdentifier(mockName)) { | |
return mockName + "." + methodName; | |
} else { | |
return methodName; | |
} | |
} | |
public void addCapture(Captures<Object> capture, Object value) { | |
capture.setPotentialValue(value); | |
currentCaptures.add(capture); | |
} | |
public void validateCaptures() { | |
for (Captures<?> c : currentCaptures) { | |
c.validateCapture(); | |
} | |
} | |
public void clearCaptures() { | |
for (Captures<?> c : currentCaptures) { | |
c.setPotentialValue(null); | |
} | |
currentCaptures.clear(); | |
} | |
private boolean toStringIsDefined(Object o) { | |
try { | |
o.getClass().getDeclaredMethod("toString", (Class[]) null) | |
.getModifiers(); | |
return true; | |
} catch (SecurityException ignored) { | |
// ///CLOVER:OFF | |
return false; | |
// ///CLOVER:ON | |
} catch (NoSuchMethodException shouldNeverHappen) { | |
// ///CLOVER:OFF | |
throw new RuntimeException("The toString() method could not be found!"); | |
// ///CLOVER:ON | |
} | |
} | |
public static boolean isJavaIdentifier(String mockName) { | |
if (mockName.length() == 0 || mockName.indexOf(' ') > -1 | |
|| !Character.isJavaIdentifierStart(mockName.charAt(0))) { | |
return false; | |
} | |
for (char c : mockName.substring(1).toCharArray()) { | |
if (!isJavaIdentifierPart(c)) { | |
return false; | |
} | |
} | |
return true; | |
} | |
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { | |
stream.defaultReadObject(); | |
try { | |
method = ((MethodSerializationWrapper) stream.readObject()).getMethod(); | |
} catch (NoSuchMethodException e) { | |
// ///CLOVER:OFF | |
throw new IOException(e.toString()); | |
// ///CLOVER:ON | |
} | |
} | |
private void writeObject(java.io.ObjectOutputStream stream) throws IOException { | |
stream.defaultWriteObject(); | |
stream.writeObject(new MethodSerializationWrapper(method)); | |
} | |
} |