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 java.io.IOException;
1947d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport java.io.Serializable;
2047d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport java.lang.reflect.InvocationHandler;
2147d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport java.lang.reflect.Method;
2247d431f63a66505a645f282416659a9758a91f1cBrett Chabotimport java.lang.reflect.Proxy;
2347d431f63a66505a645f282416659a9758a91f1cBrett Chabot
2447d431f63a66505a645f282416659a9758a91f1cBrett Chabotpublic class ObjectMethodsFilter implements InvocationHandler, Serializable {
2547d431f63a66505a645f282416659a9758a91f1cBrett Chabot
2647d431f63a66505a645f282416659a9758a91f1cBrett Chabot    private static final long serialVersionUID = -2120581954279966998L;
2747d431f63a66505a645f282416659a9758a91f1cBrett Chabot
2847d431f63a66505a645f282416659a9758a91f1cBrett Chabot    private transient Method equalsMethod;
2947d431f63a66505a645f282416659a9758a91f1cBrett Chabot
3047d431f63a66505a645f282416659a9758a91f1cBrett Chabot    private transient Method hashCodeMethod;
3147d431f63a66505a645f282416659a9758a91f1cBrett Chabot
3247d431f63a66505a645f282416659a9758a91f1cBrett Chabot    private transient Method toStringMethod;
3347d431f63a66505a645f282416659a9758a91f1cBrett Chabot
3447d431f63a66505a645f282416659a9758a91f1cBrett Chabot    private final MockInvocationHandler delegate;
3547d431f63a66505a645f282416659a9758a91f1cBrett Chabot
3647d431f63a66505a645f282416659a9758a91f1cBrett Chabot    private final String name;
3747d431f63a66505a645f282416659a9758a91f1cBrett Chabot
3847d431f63a66505a645f282416659a9758a91f1cBrett Chabot    public ObjectMethodsFilter(Class<?> toMock, MockInvocationHandler delegate,
3947d431f63a66505a645f282416659a9758a91f1cBrett Chabot            String name) {
4047d431f63a66505a645f282416659a9758a91f1cBrett Chabot        if (name != null && !Invocation.isJavaIdentifier(name)) {
4147d431f63a66505a645f282416659a9758a91f1cBrett Chabot            throw new IllegalArgumentException(String.format("'%s' is not a valid Java identifier.", name));
4247d431f63a66505a645f282416659a9758a91f1cBrett Chabot
4347d431f63a66505a645f282416659a9758a91f1cBrett Chabot        }
4447d431f63a66505a645f282416659a9758a91f1cBrett Chabot        try {
4547d431f63a66505a645f282416659a9758a91f1cBrett Chabot            if (toMock.isInterface()) {
4647d431f63a66505a645f282416659a9758a91f1cBrett Chabot                toMock = Object.class;
4747d431f63a66505a645f282416659a9758a91f1cBrett Chabot            }
4847d431f63a66505a645f282416659a9758a91f1cBrett Chabot            equalsMethod = toMock.getMethod("equals",
4947d431f63a66505a645f282416659a9758a91f1cBrett Chabot                    new Class[] { Object.class });
5047d431f63a66505a645f282416659a9758a91f1cBrett Chabot            hashCodeMethod = toMock.getMethod("hashCode", (Class[]) null);
5147d431f63a66505a645f282416659a9758a91f1cBrett Chabot            toStringMethod = toMock.getMethod("toString", (Class[]) null);
5247d431f63a66505a645f282416659a9758a91f1cBrett Chabot        } catch (NoSuchMethodException e) {
5347d431f63a66505a645f282416659a9758a91f1cBrett Chabot            // ///CLOVER:OFF
5447d431f63a66505a645f282416659a9758a91f1cBrett Chabot            throw new RuntimeException("An Object method could not be found!");
5547d431f63a66505a645f282416659a9758a91f1cBrett Chabot            // ///CLOVER:ON
5647d431f63a66505a645f282416659a9758a91f1cBrett Chabot        }
5747d431f63a66505a645f282416659a9758a91f1cBrett Chabot        this.delegate = delegate;
5847d431f63a66505a645f282416659a9758a91f1cBrett Chabot        this.name = name;
5947d431f63a66505a645f282416659a9758a91f1cBrett Chabot    }
6047d431f63a66505a645f282416659a9758a91f1cBrett Chabot
6147d431f63a66505a645f282416659a9758a91f1cBrett Chabot    public final Object invoke(Object proxy, Method method, Object[] args)
6247d431f63a66505a645f282416659a9758a91f1cBrett Chabot            throws Throwable {
6347d431f63a66505a645f282416659a9758a91f1cBrett Chabot        if (equalsMethod.equals(method)) {
6447d431f63a66505a645f282416659a9758a91f1cBrett Chabot            return Boolean.valueOf(proxy == args[0]);
6547d431f63a66505a645f282416659a9758a91f1cBrett Chabot        }
6647d431f63a66505a645f282416659a9758a91f1cBrett Chabot        if (hashCodeMethod.equals(method)) {
6747d431f63a66505a645f282416659a9758a91f1cBrett Chabot            return Integer.valueOf(System.identityHashCode(proxy));
6847d431f63a66505a645f282416659a9758a91f1cBrett Chabot        }
6947d431f63a66505a645f282416659a9758a91f1cBrett Chabot        if (toStringMethod.equals(method)) {
7047d431f63a66505a645f282416659a9758a91f1cBrett Chabot            return mockToString(proxy);
7147d431f63a66505a645f282416659a9758a91f1cBrett Chabot        }
7247d431f63a66505a645f282416659a9758a91f1cBrett Chabot        return delegate.invoke(proxy, method, args);
7347d431f63a66505a645f282416659a9758a91f1cBrett Chabot    }
7447d431f63a66505a645f282416659a9758a91f1cBrett Chabot
7547d431f63a66505a645f282416659a9758a91f1cBrett Chabot    private String mockToString(Object proxy) {
7647d431f63a66505a645f282416659a9758a91f1cBrett Chabot        return (name != null) ? name : "EasyMock for " + mockType(proxy);
7747d431f63a66505a645f282416659a9758a91f1cBrett Chabot    }
7847d431f63a66505a645f282416659a9758a91f1cBrett Chabot
7947d431f63a66505a645f282416659a9758a91f1cBrett Chabot    private String mockType(Object proxy) {
8047d431f63a66505a645f282416659a9758a91f1cBrett Chabot        if (Proxy.isProxyClass(proxy.getClass()))
8147d431f63a66505a645f282416659a9758a91f1cBrett Chabot            return proxy.getClass().getInterfaces()[0].toString();
8247d431f63a66505a645f282416659a9758a91f1cBrett Chabot        else
8347d431f63a66505a645f282416659a9758a91f1cBrett Chabot            return proxy.getClass().getSuperclass().toString();
8447d431f63a66505a645f282416659a9758a91f1cBrett Chabot    }
8547d431f63a66505a645f282416659a9758a91f1cBrett Chabot
8647d431f63a66505a645f282416659a9758a91f1cBrett Chabot    public MockInvocationHandler getDelegate() {
8747d431f63a66505a645f282416659a9758a91f1cBrett Chabot        return delegate;
8847d431f63a66505a645f282416659a9758a91f1cBrett Chabot    }
8947d431f63a66505a645f282416659a9758a91f1cBrett Chabot
9047d431f63a66505a645f282416659a9758a91f1cBrett Chabot    private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
9147d431f63a66505a645f282416659a9758a91f1cBrett Chabot        stream.defaultReadObject();
9247d431f63a66505a645f282416659a9758a91f1cBrett Chabot        try {
9347d431f63a66505a645f282416659a9758a91f1cBrett Chabot            toStringMethod = ((MethodSerializationWrapper) stream.readObject()).getMethod();
9447d431f63a66505a645f282416659a9758a91f1cBrett Chabot            equalsMethod = ((MethodSerializationWrapper) stream.readObject()).getMethod();
9547d431f63a66505a645f282416659a9758a91f1cBrett Chabot            hashCodeMethod = ((MethodSerializationWrapper) stream.readObject()).getMethod();
9647d431f63a66505a645f282416659a9758a91f1cBrett Chabot        } catch (NoSuchMethodException e) {
9747d431f63a66505a645f282416659a9758a91f1cBrett Chabot            // ///CLOVER:OFF
9847d431f63a66505a645f282416659a9758a91f1cBrett Chabot            throw new IOException(e.toString());
9947d431f63a66505a645f282416659a9758a91f1cBrett Chabot            // ///CLOVER:ON
10047d431f63a66505a645f282416659a9758a91f1cBrett Chabot        }
10147d431f63a66505a645f282416659a9758a91f1cBrett Chabot    }
10247d431f63a66505a645f282416659a9758a91f1cBrett Chabot
10347d431f63a66505a645f282416659a9758a91f1cBrett Chabot    private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
10447d431f63a66505a645f282416659a9758a91f1cBrett Chabot        stream.defaultWriteObject();
10547d431f63a66505a645f282416659a9758a91f1cBrett Chabot        stream.writeObject(new MethodSerializationWrapper(toStringMethod));
10647d431f63a66505a645f282416659a9758a91f1cBrett Chabot        stream.writeObject(new MethodSerializationWrapper(equalsMethod));
10747d431f63a66505a645f282416659a9758a91f1cBrett Chabot        stream.writeObject(new MethodSerializationWrapper(hashCodeMethod));
10847d431f63a66505a645f282416659a9758a91f1cBrett Chabot    }
10947d431f63a66505a645f282416659a9758a91f1cBrett Chabot}