1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package tests.api.java.lang.reflect;
19
20import java.lang.reflect.InvocationHandler;
21import java.lang.reflect.Method;
22import java.lang.reflect.Proxy;
23import java.lang.reflect.UndeclaredThrowableException;
24
25import tests.support.Support_Proxy_I1;
26import tests.support.Support_Proxy_I2;
27import tests.support.Support_Proxy_ParentException;
28import tests.support.Support_Proxy_SubException;
29
30public class ProxyTest extends junit.framework.TestCase {
31
32    /*
33     * When multiple interfaces define the same method, the list of thrown
34     * exceptions are those which can be mapped to another exception in the
35     * other method:
36     *
37     * String foo(String s) throws SubException, LinkageError;
38     *
39     * UndeclaredThrowableException wrappers any checked exception which is not
40     * in the merged list. So ParentException would be wrapped, BUT LinkageError
41     * would not be since its not an Error/RuntimeException.
42     *
43     * interface I1 { String foo(String s) throws ParentException, LinkageError; }
44     * interface I2 { String foo(String s) throws SubException, Error; }
45     */
46
47    interface Broken1 {
48        public float method(float _number0, float _number1);
49    }
50
51    class Broken1Invoke implements InvocationHandler {
52        public Object invoke(Object proxy, Method method, Object[] args)
53                throws Throwable {
54            return args[1];
55        }
56    }
57
58    class ProxyCoonstructorTest extends Proxy {
59        protected ProxyCoonstructorTest(InvocationHandler h) {
60            super(h);
61        }
62    }
63
64    /**
65     * java.lang.reflect.Proxy#getProxyClass(java.lang.ClassLoader,
66     *        java.lang.Class[])
67     */
68    public void test_getProxyClassLjava_lang_ClassLoader$Ljava_lang_Class() {
69        Class proxy = Proxy.getProxyClass(Support_Proxy_I1.class
70                .getClassLoader(), new Class[] { Support_Proxy_I1.class });
71
72        assertTrue("Did not create a Proxy subclass ",
73                proxy.getSuperclass() == Proxy.class);
74        assertTrue("Does not believe its a Proxy class ", Proxy
75                .isProxyClass(proxy));
76
77        assertTrue("Does not believe it's a Proxy class ", Proxy
78                .isProxyClass(Proxy.getProxyClass(null,
79                        new Class[] { Comparable.class })));
80
81        try {
82            Proxy.getProxyClass(Support_Proxy_I1.class.getClassLoader(),
83                    (Class<?>[]) null);
84            fail("NPE expected");
85        } catch (NullPointerException expected) {
86        }
87
88        try {
89            Proxy.getProxyClass(Support_Proxy_I1.class.getClassLoader(),
90                    new Class<?>[] {Support_Proxy_I1.class, null});
91            fail("NPE expected");
92        } catch (NullPointerException expected) {
93        }
94    }
95
96    /**
97     * java.lang.reflect.Proxy#Proxy(java.lang.reflect.InvocationHandler)
98     */
99    public void test_ProxyLjava_lang_reflect_InvocationHandler() {
100        assertNotNull(new ProxyCoonstructorTest(new InvocationHandler() {
101            public Object invoke(Object proxy, Method method, Object[] args)
102                    throws Throwable {
103                return null;
104            }
105        }));
106    }
107
108
109
110    /**
111     * java.lang.reflect.Proxy#newProxyInstance(java.lang.ClassLoader,
112     *        java.lang.Class[], java.lang.reflect.InvocationHandler)
113     */
114    public void test_newProxyInstanceLjava_lang_ClassLoader$Ljava_lang_ClassLjava_lang_reflect_InvocationHandler() {
115        Object p = Proxy.newProxyInstance(Support_Proxy_I1.class
116                .getClassLoader(), new Class[] { Support_Proxy_I1.class,
117                Support_Proxy_I2.class }, new InvocationHandler() {
118            public Object invoke(Object proxy, Method method, Object[] args)
119                    throws Throwable {
120                if (method.getName().equals("equals"))
121                    return new Boolean(proxy == args[0]);
122                if (method.getName().equals("array"))
123                    return new int[] { (int) ((long[]) args[0])[1], -1 };
124                if (method.getName().equals("string")) {
125                    if ("".equals(args[0]))
126                        throw new Support_Proxy_SubException();
127                    if ("clone".equals(args[0]))
128                        throw new Support_Proxy_ParentException();
129                    if ("error".equals(args[0]))
130                        throw new ArrayStoreException();
131                    if ("any".equals(args[0]))
132                        throw new IllegalAccessException();
133                }
134                return null;
135            }
136        });
137
138        Support_Proxy_I1 proxy = (Support_Proxy_I1) p;
139        assertTrue("Failed identity test ", proxy.equals(proxy));
140        assertTrue("Failed not equals test ", !proxy.equals(""));
141        int[] result = (int[]) proxy.array(new long[] { 100L, -200L });
142        assertEquals("Failed primitive type conversion test ", -200, result[0]);
143
144        boolean worked = false;
145        try {
146            proxy.string("");
147        } catch (Support_Proxy_SubException e) {
148            worked = true;
149        } catch (Support_Proxy_ParentException e) { // is never thrown
150        }
151        assertTrue("Problem converting exception ", worked);
152
153        worked = false;
154        try {
155            proxy.string("clone");
156        } catch (Support_Proxy_ParentException e) { // is never thrown
157        } catch (UndeclaredThrowableException e) {
158            worked = true;
159        }
160        assertTrue("Problem converting exception ", worked);
161
162        worked = false;
163        try {
164            proxy.string("error");
165        } catch (Support_Proxy_ParentException e) { // is never thrown
166        } catch (UndeclaredThrowableException e) {
167        } catch (RuntimeException e) {
168            worked = e.getClass() == ArrayStoreException.class;
169        }
170        assertTrue("Problem converting exception ", worked);
171
172        worked = false;
173        try {
174            proxy.string("any");
175        } catch (Support_Proxy_ParentException e) { // is never thrown
176        } catch (UndeclaredThrowableException e) {
177            worked = true;
178        }
179        assertTrue("Problem converting exception ", worked);
180
181        Broken1 proxyObject = null;
182        try {
183            proxyObject = (Broken1) Proxy.newProxyInstance(Broken1.class
184                    .getClassLoader(), new Class[] { Broken1.class },
185                    new Broken1Invoke());
186        } catch (Throwable e) {
187            fail("Failed to create proxy for class: " + Broken1.class + " - "
188                    + e);
189        }
190        float brokenResult = proxyObject.method(2.1f, 5.8f);
191        assertTrue("Invalid invoke result", brokenResult == 5.8f);
192    }
193
194    /**
195     * java.lang.reflect.Proxy#isProxyClass(java.lang.Class)
196     */
197    public void test_isProxyClassLjava_lang_Class() {
198        Class proxy = Proxy.getProxyClass(Support_Proxy_I1.class
199                .getClassLoader(), new Class[] { Support_Proxy_I1.class });
200
201        class Fake extends Proxy {
202            Fake() {
203                super(null);
204            }
205        }
206
207        Proxy fake = new Proxy(new InvocationHandler() {
208            public Object invoke(Object proxy, Method method, Object[] args)
209                    throws Throwable {
210                return null;
211            }
212        }) {
213        };
214
215        assertTrue("Does not believe its a Proxy class ", Proxy
216                .isProxyClass(proxy));
217        assertTrue("Proxy subclasses do not count ", !Proxy
218                .isProxyClass(Fake.class));
219        assertTrue("Is not a runtime generated Proxy class ", !Proxy
220                .isProxyClass(fake.getClass()));
221        boolean thrown = false;
222        try{
223        Proxy.isProxyClass(null);
224        } catch (NullPointerException ex){
225            thrown = true;
226        }
227        assertTrue("NPE not thrown.", thrown);
228    }
229
230    /**
231     * java.lang.reflect.Proxy#getInvocationHandler(java.lang.Object)
232     */
233    public void test_getInvocationHandlerLjava_lang_Object() {
234        InvocationHandler handler = new InvocationHandler() {
235            public Object invoke(Object proxy, Method method, Object[] args)
236                    throws Throwable {
237                return null;
238            }
239        };
240
241        Object p = Proxy.newProxyInstance(Support_Proxy_I1.class
242                .getClassLoader(), new Class[] { Support_Proxy_I1.class },
243                handler);
244
245        assertTrue("Did not return invocation handler ", Proxy
246                .getInvocationHandler(p) == handler);
247        boolean aborted = false;
248        try {
249            Proxy.getInvocationHandler("");
250        } catch (IllegalArgumentException e) {
251            aborted = true;
252        }
253        assertTrue("Did not detect non proxy object ", aborted);
254    }
255
256    //Regression Test for HARMONY-2355
257    public void test_newProxyInstance_withCompatibleReturnTypes() {
258        Object o = Proxy
259                .newProxyInstance(this.getClass().getClassLoader(),
260                        new Class[] { ITestReturnObject.class,
261                                ITestReturnString.class },
262                        new TestProxyHandler(new TestProxyImpl()));
263        assertNotNull(o);
264    }
265
266    public void test_newProxyInstance_withNonCompatibleReturnTypes() {
267        try {
268            Proxy.newProxyInstance(this.getClass().getClassLoader(),
269                    new Class[] { ITestReturnInteger.class,
270                            ITestReturnString.class }, new TestProxyHandler(
271                            new TestProxyImpl()));
272            fail("should throw IllegalArgumentException");
273        } catch (IllegalArgumentException e) {
274            // expected
275        }
276
277    }
278
279    public static interface ITestReturnObject {
280        Object f();
281    }
282
283    public static interface ITestReturnString {
284        String f();
285    }
286
287    public static interface ITestReturnInteger {
288        Integer f();
289    }
290
291    public static class TestProxyImpl implements ITestReturnObject,
292            ITestReturnString {
293        public String f() {
294            // do nothing
295            return null;
296        }
297    }
298
299    public static class TestProxyHandler implements InvocationHandler {
300        private Object proxied;
301
302        public TestProxyHandler(Object object) {
303            proxied = object;
304        }
305
306        public Object invoke(Object object, Method method, Object[] args)
307                throws Throwable {
308            // do nothing
309            return method.invoke(proxied, args);
310        }
311
312    }
313
314    protected void setUp() {
315    }
316
317    protected void tearDown() {
318    }
319}
320