1674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/*
2674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Copyright 2003,2004 The Apache Software Foundation
3674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *
4674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *  Licensed under the Apache License, Version 2.0 (the "License");
5674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * you may not use this file except in compliance with the License.
6674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * You may obtain a copy of the License at
7674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *
8674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *      http://www.apache.org/licenses/LICENSE-2.0
9674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *
10674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *  Unless required by applicable law or agreed to in writing, software
11674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * distributed under the License is distributed on an "AS IS" BASIS,
12674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * See the License for the specific language governing permissions and
14674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * limitations under the License.
15674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */
16674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpackage org.mockito.cglib.proxy;
17674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
18674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.io.Serializable;
19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.lang.reflect.Method;
20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport java.util.List;
21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenimport org.mockito.cglib.core.CodeGenerationException;
23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/**
25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * This class is meant to be used as replacement for
26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <code>java.lang.reflect.Proxy</code> under JDK 1.2. There are some known
27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * subtle differences:
28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <ul>
29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <li>The exceptions returned by invoking <code>getExceptionTypes</code>
30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * on the <code>Method</code> passed to the <code>invoke</code> method
31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <b>are</b> the exact set that can be thrown without resulting in an
32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <code>UndeclaredThrowableException</code> being thrown.
33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <li>{@link UndeclaredThrowableException} is used instead
34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * of <code>java.lang.reflect.UndeclaredThrowableException</code>.
35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * </ul>
36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * <p>
37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @version $Id: Proxy.java,v 1.6 2004/06/24 21:15:19 herbyderby Exp $
38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */
39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpublic class Proxy implements Serializable {
40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    protected InvocationHandler h;
41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static final CallbackFilter BAD_OBJECT_METHOD_FILTER = new CallbackFilter() {
43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        public int accept(Method method, List<Method> allMethods) {
44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            if (method.getDeclaringClass().getName().equals("java.lang.Object")) {
45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                String name = method.getName();
46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                if (!(name.equals("hashCode") ||
47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                      name.equals("equals") ||
48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                      name.equals("toString"))) {
49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                    return 1;
50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen                }
51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            }
52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return 0;
53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    };
55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    protected Proxy(InvocationHandler h) {
57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Enhancer.registerCallbacks(getClass(), new Callback[]{ h, null });
58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        this.h = h;
59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // private for security of isProxyClass
62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private static class ProxyImpl extends Proxy {
63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        protected ProxyImpl(InvocationHandler h) {
64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            super(h);
65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public static InvocationHandler getInvocationHandler(Object proxy) {
69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!(proxy instanceof ProxyImpl)) {
70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new IllegalArgumentException("Object is not a proxy");
71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return ((Proxy)proxy).h;
73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public static Class getProxyClass(ClassLoader loader, Class[] interfaces) {
76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        Enhancer e = new Enhancer();
77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        e.setSuperclass(ProxyImpl.class);
78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        e.setInterfaces(interfaces);
79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        e.setCallbackTypes(new Class[]{
80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            InvocationHandler.class,
81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            NoOp.class,
82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        });
83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        e.setCallbackFilter(BAD_OBJECT_METHOD_FILTER);
84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        e.setUseFactory(false);
85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return e.createClass();
86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public static boolean isProxyClass(Class cl) {
89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return cl.getSuperclass().equals(ProxyImpl.class);
90674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
91674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
92674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) {
93674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        try {
94674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            Class clazz = getProxyClass(loader, interfaces);
95674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            return clazz.getConstructor(new Class[]{ InvocationHandler.class }).newInstance(new Object[]{ h });
96674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } catch (RuntimeException e) {
97674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw e;
98674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        } catch (Exception e) {
99674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            throw new CodeGenerationException(e);
100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen}
103