| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.apache.struts2.json; |
| |
| import java.lang.reflect.InvocationHandler; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.Proxy; |
| |
| import junit.framework.TestCase; |
| |
| import org.apache.struts2.json.annotations.SMDMethod; |
| |
| /** |
| * Tests that the SMDMethod annotation can be found in interfaces when |
| * ignoreSMDMethodInterface is false |
| */ |
| public class SMDMethodInterfaceTest extends TestCase { |
| |
| public interface InterfaceA { |
| String getA(); |
| } |
| |
| public interface InterfaceB { |
| @SMDMethod |
| String getB(); |
| } |
| |
| public interface InterfaceC { |
| String getC(); |
| } |
| |
| public interface InterfaceD { |
| String getD(); |
| } |
| |
| public interface InterfaceE { |
| String getE(); |
| } |
| |
| public static class ClassA extends ClassB implements InterfaceA { |
| |
| private String a; |
| private String z; |
| |
| public ClassA(String a, String b, String c, String d, String e, String x, String y, String z) { |
| super(b, c, d, e, x, y); |
| this.a = a; |
| this.z = z; |
| } |
| |
| public String getA() { |
| return a; |
| } |
| |
| @SMDMethod |
| public String getZ() { |
| return z; |
| } |
| } |
| |
| public static class ClassB extends ClassC implements InterfaceB, InterfaceC { |
| |
| private String b; |
| private String c; |
| private String y; |
| |
| public ClassB(String b, String c, String d, String e, String x, String y) { |
| super(d, e, x); |
| this.b = b; |
| this.c = c; |
| this.y = y; |
| } |
| |
| public String getC() { |
| return c; |
| } |
| |
| public String getB() { |
| return b; |
| } |
| |
| public String getY() { |
| return y; |
| } |
| } |
| |
| public static class ClassC implements InterfaceD, InterfaceE { |
| |
| private String d; |
| private String e; |
| private String x; |
| |
| public ClassC(String d, String e, String x) { |
| this.d = d; |
| this.e = e; |
| this.x = x; |
| } |
| |
| public String getD() { |
| return d; |
| } |
| |
| public String getE() { |
| return e; |
| } |
| |
| @SMDMethod |
| public String getX() { |
| return x; |
| } |
| } |
| |
| /** |
| * Asserts that the SMDMethod annotation is only detected on the classes |
| * when ignoreSMDMethodInterfaces is true |
| */ |
| public void testBaseClassOnly() { |
| Method[] smdMethodsA = JSONUtil.listSMDMethods(ClassA.class, true); |
| assertEquals(2, smdMethodsA.length); |
| assertEquals("getZ", smdMethodsA[0].getName()); |
| assertEquals("getX", smdMethodsA[1].getName()); |
| |
| Method[] smdMethodsB = JSONUtil.listSMDMethods(ClassB.class, true); |
| assertEquals(1, smdMethodsB.length); |
| assertEquals("getX", smdMethodsB[0].getName()); |
| |
| Method[] smdMethodsC = JSONUtil.listSMDMethods(ClassC.class, true); |
| assertEquals(1, smdMethodsC.length); |
| assertEquals("getX", smdMethodsC[0].getName()); |
| } |
| |
| /** |
| * Asserts that the SMDMethod annotation is also detected on the interfaces |
| * and superclasses when ignoreSMDMethodInterfaces is false |
| */ |
| public void testInterfaces() { |
| Method[] smdMethodsA = JSONUtil.listSMDMethods(ClassA.class, false); |
| assertEquals(3, smdMethodsA.length); |
| assertEquals("getZ", smdMethodsA[0].getName()); |
| assertEquals("getX", smdMethodsA[1].getName()); |
| assertEquals("getB", smdMethodsA[2].getName()); |
| |
| Method[] smdMethodsB = JSONUtil.listSMDMethods(ClassB.class, false); |
| assertEquals(2, smdMethodsB.length); |
| assertEquals("getX", smdMethodsB[0].getName()); |
| assertEquals("getB", smdMethodsB[1].getName()); |
| |
| Method[] smdMethodsC = JSONUtil.listSMDMethods(ClassC.class, false); |
| assertEquals(1, smdMethodsC.length); |
| assertEquals("getX", smdMethodsC[0].getName()); |
| } |
| |
| /** |
| * This is the important case: detects the SMDMethod annotation on a proxy |
| */ |
| public void testWithProxy() { |
| |
| InvocationHandler handler = new InvocationHandler() { |
| // dummy implementation |
| public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { |
| return null; |
| } |
| }; |
| // proxy is proxy to an impl of ClassA |
| InterfaceA proxy = (InterfaceA) Proxy.newProxyInstance(ClassA.class.getClassLoader(), new Class[] { |
| InterfaceA.class, InterfaceB.class, InterfaceC.class }, handler); |
| |
| // first, without the recursion |
| Method[] smdMethodsA = JSONUtil.listSMDMethods(proxy.getClass(), true); |
| assertEquals(0, smdMethodsA.length); |
| |
| // now with the recursion |
| Method[] smdMethodsB = JSONUtil.listSMDMethods(proxy.getClass(), false); |
| assertEquals(1, smdMethodsB.length); |
| assertEquals("getB", smdMethodsB[0].getName()); |
| } |
| } |