001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.proxy2;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertFalse;
022import static org.junit.Assert.assertTrue;
023
024import java.util.Date;
025
026import org.apache.commons.proxy2.exception.ProxyFactoryException;
027import org.apache.commons.proxy2.invoker.NullInvoker;
028import org.apache.commons.proxy2.provider.ConstantProvider;
029import org.apache.commons.proxy2.util.AbstractEcho;
030import org.apache.commons.proxy2.util.Echo;
031import org.apache.commons.proxy2.util.EchoImpl;
032import org.junit.Test;
033
034@SuppressWarnings("serial")
035public abstract class AbstractSubclassingProxyFactoryTestCase extends AbstractProxyFactoryTestCase
036{
037    //----------------------------------------------------------------------------------------------------------------------
038    // Fields
039    //----------------------------------------------------------------------------------------------------------------------
040
041    private static final Class<?>[] DATE_ONLY = new Class[] { Date.class };
042
043    //----------------------------------------------------------------------------------------------------------------------
044    // Other Methods
045    //----------------------------------------------------------------------------------------------------------------------
046
047    @Override
048    @Test
049    public void testCanProxy()
050    {
051        assertTrue(factory.canProxy(new Class[] { Echo.class }));
052        assertTrue(factory.canProxy(new Class[] { EchoImpl.class }));
053        assertFalse(factory.canProxy(new Class[] { FinalEcho.class }));
054        assertTrue(factory.canProxy(new Class[] { FinalMethodEcho.class, Echo.class }));
055        assertFalse(factory.canProxy(new Class[] { NoDefaultConstructorEcho.class }));
056        assertTrue(factory.canProxy(new Class[] { ProtectedConstructorEcho.class }));
057        assertFalse(factory.canProxy(new Class[] { InvisibleEcho.class }));
058        assertFalse(factory.canProxy(new Class[] { Echo.class, EchoImpl.class, String.class }));
059    }
060
061    @Override
062    @Test
063    public void testDelegatorEquals() throws Exception
064    {
065        final EqualsEcho echo = new EqualsEcho("text");
066        final Echo proxy1 = factory.createDelegatorProxy(new ConstantProvider<Echo>(echo),
067                new Class[] { EqualsEcho.class });
068        final Echo proxy2 = factory.createDelegatorProxy(new ConstantProvider<Echo>(echo),
069                new Class[] { EqualsEcho.class });
070        assertEquals(proxy1, proxy1);
071        assertFalse(proxy1.equals(proxy2));
072        assertFalse(proxy2.equals(proxy1));
073    }
074
075    @Test(expected = ProxyFactoryException.class)
076    public void testDelegatorWithMultipleSuperclasses()
077    {
078        factory.createDelegatorProxy(new ConstantProvider<EchoImpl>(new EchoImpl()), new Class[] { EchoImpl.class,
079                String.class });
080    }
081
082    @Test
083    public void testDelegatorWithSuperclass()
084    {
085        final Echo echo = factory.createDelegatorProxy(new ConstantProvider<EchoImpl>(new EchoImpl()), new Class[] {
086                Echo.class, EchoImpl.class });
087        assertTrue(echo instanceof EchoImpl);
088    }
089
090    @Override
091    @Test
092    public void testInterceptorEquals()
093    {
094        final EqualsEcho echo = new EqualsEcho("text");
095        final Echo proxy1 = factory.createInterceptorProxy(echo, new NoOpMethodInterceptor(),
096                new Class[] { EqualsEcho.class });
097        final Echo proxy2 = factory.createInterceptorProxy(echo, new NoOpMethodInterceptor(),
098                new Class[] { EqualsEcho.class });
099        assertEquals(proxy1, proxy1);
100        assertFalse(proxy1.equals(proxy2));
101        assertFalse(proxy2.equals(proxy1));
102    }
103
104    @Test(expected = ProxyFactoryException.class)
105    public void testInterceptorWithMultipleSuperclasses()
106    {
107        factory.createInterceptorProxy(new EchoImpl(), new NoOpMethodInterceptor(), new Class[] { EchoImpl.class,
108                String.class });
109    }
110
111    @Test
112    public void testInterceptorWithSuperclass()
113    {
114        final Echo echo = factory.createInterceptorProxy(new EchoImpl(), new NoOpMethodInterceptor(), new Class[] {
115                Echo.class, EchoImpl.class });
116        assertTrue(echo instanceof EchoImpl);
117    }
118
119    @Test(expected = ProxyFactoryException.class)
120    public void testInvocationHandlerWithMultipleSuperclasses()
121    {
122        factory.createInvokerProxy(new NullInvoker(), new Class[] { EchoImpl.class, String.class });
123    }
124
125    @Override
126    @Test
127    public void testInvokerEquals() throws Exception
128    {
129        final Date proxy1 = factory.createInvokerProxy(new InvokerTester(), DATE_ONLY);
130        final Date proxy2 = factory.createInvokerProxy(new InvokerTester(), DATE_ONLY);
131        assertEquals(proxy1, proxy1);
132        assertFalse(proxy1.equals(proxy2));
133        assertFalse(proxy2.equals(proxy1));
134    }
135
136    @Test
137    public void testInvokerWithSuperclass()
138    {
139        final Echo echo = factory.createInvokerProxy(new NullInvoker(), new Class[] { Echo.class, EchoImpl.class });
140        assertTrue(echo instanceof EchoImpl);
141    }
142
143    @Test
144    public void testProxiesWithClashingFinalMethodInSuperclass()
145    {
146        final Class<?>[] proxyClasses = new Class[] { Echo.class, FinalMethodEcho.class };
147        Echo proxy = factory.createDelegatorProxy(new ConstantProvider<EchoImpl>(new EchoImpl()), proxyClasses);
148        assertEquals("final", proxy.echoBack("echo"));
149
150        proxy = factory.createInterceptorProxy(new EchoImpl(), new NoOpMethodInterceptor(), proxyClasses);
151        assertEquals("final", proxy.echoBack("echo"));
152
153        proxy = factory.createInvokerProxy(new NullInvoker(), proxyClasses);
154        assertEquals("final", proxy.echoBack("echo"));
155    }
156
157    @Test
158    public void testWithAbstractSuperclass()
159    {
160        final Echo echo = factory.createDelegatorProxy(new ConstantProvider<EchoImpl>(new EchoImpl()),
161                new Class[] { AbstractEcho.class });
162        assertEquals("hello", echo.echoBack("hello"));
163        assertEquals("helloworld", echo.echoBack("hello", "world"));
164    }
165
166    //----------------------------------------------------------------------------------------------------------------------
167    // Inner Classes
168    //----------------------------------------------------------------------------------------------------------------------
169
170    public static class EqualsEcho extends EchoImpl
171    {
172        @SuppressWarnings("unused")
173        private final String text;
174
175        protected EqualsEcho()
176        {
177            this("testing");
178        }
179
180        public EqualsEcho(String text)
181        {
182            this.text = text;
183        }
184    }
185
186    public static final class FinalEcho extends EchoImpl
187    {
188    }
189
190    public static class FinalMethodEcho extends EchoImpl
191    {
192        @Override
193        public final String echoBack(String message)
194        {
195            return "final";
196        }
197    }
198
199    private static class InvisibleEcho extends EchoImpl
200    {
201    }
202
203    public static class NoDefaultConstructorEcho extends EchoImpl
204    {
205        public NoDefaultConstructorEcho(String param)
206        {
207        }
208    }
209
210    public static class ProtectedConstructorEcho extends EchoImpl
211    {
212        protected ProtectedConstructorEcho()
213        {
214        }
215    }
216}