1 /* 2 * Copyright (C) 2006 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.inject.internal; 18 19 import static com.google.inject.matcher.Matchers.annotatedWith; 20 import static com.google.inject.matcher.Matchers.any; 21 import static com.google.inject.matcher.Matchers.not; 22 import static com.google.inject.matcher.Matchers.only; 23 24 import com.google.common.collect.Lists; 25 import com.google.inject.Inject; 26 import com.google.inject.spi.InjectionPoint; 27 import java.lang.annotation.Retention; 28 import java.lang.annotation.RetentionPolicy; 29 import java.lang.reflect.InvocationTargetException; 30 import java.util.List; 31 import junit.framework.TestCase; 32 import org.aopalliance.intercept.MethodInterceptor; 33 import org.aopalliance.intercept.MethodInvocation; 34 35 /** @author crazybob@google.com (Bob Lee) */ 36 public class ProxyFactoryTest extends TestCase { 37 38 List<MethodAspect> aspects = Lists.newArrayList(); 39 testSimpleCase()40 public void testSimpleCase() 41 throws NoSuchMethodException, InvocationTargetException, ErrorsException { 42 SimpleInterceptor interceptor = new SimpleInterceptor(); 43 InjectionPoint injectionPoint = InjectionPoint.forConstructorOf(Simple.class); 44 45 aspects.add(new MethodAspect(any(), any(), interceptor)); 46 ProxyFactory<Simple> factory = new ProxyFactory<>(injectionPoint, aspects); 47 48 ConstructionProxy<Simple> constructionProxy = factory.create(); 49 50 Simple simple = constructionProxy.newInstance(); 51 simple.invoke(); 52 assertTrue(simple.invoked); 53 assertTrue(interceptor.invoked); 54 } 55 56 static class Simple { 57 boolean invoked = false; 58 invoke()59 public void invoke() { 60 invoked = true; 61 } 62 } 63 64 static class SimpleInterceptor implements MethodInterceptor { 65 66 boolean invoked = false; 67 68 @Override invoke(MethodInvocation methodInvocation)69 public Object invoke(MethodInvocation methodInvocation) throws Throwable { 70 invoked = true; 71 return methodInvocation.proceed(); 72 } 73 } 74 testInterceptOneMethod()75 public void testInterceptOneMethod() 76 throws NoSuchMethodException, InvocationTargetException, ErrorsException { 77 SimpleInterceptor interceptor = new SimpleInterceptor(); 78 79 aspects.add(new MethodAspect(only(Bar.class), annotatedWith(Intercept.class), interceptor)); 80 81 ConstructionProxy<Foo> fooFactory = 82 new ProxyFactory<Foo>(InjectionPoint.forConstructorOf(Foo.class), aspects).create(); 83 ConstructionProxy<Bar> barFactory = 84 new ProxyFactory<Bar>(InjectionPoint.forConstructorOf(Bar.class), aspects).create(); 85 86 Foo foo = fooFactory.newInstance(); 87 Bar bar = barFactory.newInstance(); 88 89 foo.foo(); 90 assertTrue(foo.fooCalled); 91 assertFalse(interceptor.invoked); 92 93 bar.bar(); 94 assertTrue(bar.barCalled); 95 assertFalse(interceptor.invoked); 96 97 bar.intercepted(); 98 assertTrue(bar.interceptedCalled); 99 assertTrue(interceptor.invoked); 100 } 101 102 static class Foo { 103 boolean fooCalled; 104 105 @Intercept foo()106 void foo() { 107 fooCalled = true; 108 } 109 } 110 111 static class Bar { 112 113 boolean barCalled; 114 bar()115 void bar() { 116 barCalled = true; 117 } 118 119 boolean interceptedCalled; 120 121 @Intercept intercepted()122 void intercepted() { 123 interceptedCalled = true; 124 } 125 } 126 127 @Retention(RetentionPolicy.RUNTIME) 128 @interface Intercept {} 129 testWithConstructorArguments()130 public void testWithConstructorArguments() 131 throws InvocationTargetException, NoSuchMethodException, ErrorsException { 132 SimpleInterceptor interceptor = new SimpleInterceptor(); 133 134 aspects.add(new MethodAspect(any(), any(), interceptor)); 135 ProxyFactory<A> factory = 136 new ProxyFactory<A>(InjectionPoint.forConstructorOf(A.class), aspects); 137 138 ConstructionProxy<A> constructor = factory.create(); 139 140 A a = constructor.newInstance(5); 141 a.a(); 142 assertEquals(5, a.i); 143 } 144 testNotProxied()145 public void testNotProxied() 146 throws NoSuchMethodException, InvocationTargetException, ErrorsException { 147 SimpleInterceptor interceptor = new SimpleInterceptor(); 148 149 aspects.add(new MethodAspect(not(any()), not(any()), interceptor)); 150 ProxyFactory<A> factory = 151 new ProxyFactory<A>(InjectionPoint.forConstructorOf(A.class), aspects); 152 153 ConstructionProxy<A> constructor = factory.create(); 154 155 A a = constructor.newInstance(5); 156 assertEquals(A.class, a.getClass()); 157 } 158 159 static class A { 160 final int i; 161 162 @Inject A(int i)163 public A(int i) { 164 this.i = i; 165 } 166 a()167 public void a() {} 168 } 169 testMultipleInterceptors()170 public void testMultipleInterceptors() 171 throws NoSuchMethodException, InvocationTargetException, ErrorsException { 172 DoubleInterceptor doubleInterceptor = new DoubleInterceptor(); 173 CountingInterceptor countingInterceptor = new CountingInterceptor(); 174 175 aspects.add(new MethodAspect(any(), any(), doubleInterceptor, countingInterceptor)); 176 ProxyFactory<Counter> factory = 177 new ProxyFactory<Counter>(InjectionPoint.forConstructorOf(Counter.class), aspects); 178 179 ConstructionProxy<Counter> constructor = factory.create(); 180 181 Counter counter = constructor.newInstance(); 182 counter.inc(); 183 assertEquals(2, counter.count); 184 assertEquals(2, countingInterceptor.count); 185 } 186 187 static class CountingInterceptor implements MethodInterceptor { 188 189 int count; 190 191 @Override invoke(MethodInvocation methodInvocation)192 public Object invoke(MethodInvocation methodInvocation) throws Throwable { 193 count++; 194 return methodInvocation.proceed(); 195 } 196 } 197 198 static class DoubleInterceptor implements MethodInterceptor { 199 200 @Override invoke(MethodInvocation methodInvocation)201 public Object invoke(MethodInvocation methodInvocation) throws Throwable { 202 methodInvocation.proceed(); 203 return methodInvocation.proceed(); 204 } 205 } 206 207 static class Counter { 208 int count; 209 inc()210 void inc() { 211 count++; 212 } 213 } 214 } 215