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 28 import junit.framework.TestCase; 29 30 import org.aopalliance.intercept.MethodInterceptor; 31 import org.aopalliance.intercept.MethodInvocation; 32 33 import java.lang.annotation.Retention; 34 import java.lang.annotation.RetentionPolicy; 35 import java.lang.reflect.InvocationTargetException; 36 import java.util.List; 37 38 /** 39 * @author crazybob@google.com (Bob Lee) 40 */ 41 public class ProxyFactoryTest extends TestCase { 42 43 List<MethodAspect> aspects = Lists.newArrayList(); 44 testSimpleCase()45 public void testSimpleCase() 46 throws NoSuchMethodException, InvocationTargetException, ErrorsException { 47 SimpleInterceptor interceptor = new SimpleInterceptor(); 48 InjectionPoint injectionPoint = InjectionPoint.forConstructorOf(Simple.class); 49 50 aspects.add(new MethodAspect(any(), any(), interceptor)); 51 ProxyFactory<Simple> factory = new ProxyFactory<Simple>(injectionPoint, aspects); 52 53 ConstructionProxy<Simple> constructionProxy = factory.create(); 54 55 Simple simple = constructionProxy.newInstance(); 56 simple.invoke(); 57 assertTrue(simple.invoked); 58 assertTrue(interceptor.invoked); 59 } 60 61 static class Simple { 62 boolean invoked = false; invoke()63 public void invoke() { 64 invoked = true; 65 } 66 } 67 68 static class SimpleInterceptor implements MethodInterceptor { 69 70 boolean invoked = false; 71 invoke(MethodInvocation methodInvocation)72 public Object invoke(MethodInvocation methodInvocation) throws Throwable { 73 invoked = true; 74 return methodInvocation.proceed(); 75 } 76 } 77 testInterceptOneMethod()78 public void testInterceptOneMethod() 79 throws NoSuchMethodException, InvocationTargetException, ErrorsException { 80 SimpleInterceptor interceptor = new SimpleInterceptor(); 81 82 aspects.add(new MethodAspect(only(Bar.class), annotatedWith(Intercept.class), interceptor)); 83 84 ConstructionProxy<Foo> fooFactory 85 = new ProxyFactory<Foo>(InjectionPoint.forConstructorOf(Foo.class), aspects).create(); 86 ConstructionProxy<Bar> barFactory 87 = new ProxyFactory<Bar>(InjectionPoint.forConstructorOf(Bar.class), aspects).create(); 88 89 Foo foo = fooFactory.newInstance(); 90 Bar bar = barFactory.newInstance(); 91 92 foo.foo(); 93 assertTrue(foo.fooCalled); 94 assertFalse(interceptor.invoked); 95 96 bar.bar(); 97 assertTrue(bar.barCalled); 98 assertFalse(interceptor.invoked); 99 100 bar.intercepted(); 101 assertTrue(bar.interceptedCalled); 102 assertTrue(interceptor.invoked); 103 } 104 105 static class Foo { 106 boolean fooCalled; 107 @Intercept foo()108 void foo() { 109 fooCalled = true; 110 } 111 } 112 113 static class Bar { 114 115 boolean barCalled; bar()116 void bar() { 117 barCalled = true; 118 } 119 120 boolean interceptedCalled; 121 122 @Intercept intercepted()123 void intercepted() { 124 interceptedCalled = true; 125 } 126 } 127 128 @Retention(RetentionPolicy.RUNTIME) 129 @interface Intercept {} 130 testWithConstructorArguments()131 public void testWithConstructorArguments() 132 throws InvocationTargetException, NoSuchMethodException, ErrorsException { 133 SimpleInterceptor interceptor = new SimpleInterceptor(); 134 135 aspects.add(new MethodAspect(any(), any(), interceptor)); 136 ProxyFactory<A> factory 137 = new ProxyFactory<A>(InjectionPoint.forConstructorOf(A.class), aspects); 138 139 ConstructionProxy<A> constructor = factory.create(); 140 141 A a = constructor.newInstance(5); 142 a.a(); 143 assertEquals(5, a.i); 144 } 145 testNotProxied()146 public void testNotProxied() 147 throws NoSuchMethodException, InvocationTargetException, ErrorsException { 148 SimpleInterceptor interceptor = new SimpleInterceptor(); 149 150 aspects.add(new MethodAspect(not(any()), not(any()), interceptor)); 151 ProxyFactory<A> factory 152 = new ProxyFactory<A>(InjectionPoint.forConstructorOf(A.class), aspects); 153 154 ConstructionProxy<A> constructor = factory.create(); 155 156 A a = constructor.newInstance(5); 157 assertEquals(A.class, a.getClass()); 158 } 159 160 static class A { 161 final int i; A(int i)162 @Inject public A(int i) { 163 this.i = i; 164 } a()165 public void a() {} 166 } 167 testMultipleInterceptors()168 public void testMultipleInterceptors() 169 throws NoSuchMethodException, InvocationTargetException, ErrorsException { 170 DoubleInterceptor doubleInterceptor = new DoubleInterceptor(); 171 CountingInterceptor countingInterceptor = new CountingInterceptor(); 172 173 aspects.add(new MethodAspect(any(), any(), doubleInterceptor, countingInterceptor)); 174 ProxyFactory<Counter> factory 175 = new ProxyFactory<Counter>(InjectionPoint.forConstructorOf(Counter.class), aspects); 176 177 ConstructionProxy<Counter> constructor = factory.create(); 178 179 Counter counter = constructor.newInstance(); 180 counter.inc(); 181 assertEquals(2, counter.count); 182 assertEquals(2, countingInterceptor.count); 183 } 184 185 static class CountingInterceptor implements MethodInterceptor { 186 187 int count; 188 invoke(MethodInvocation methodInvocation)189 public Object invoke(MethodInvocation methodInvocation) throws Throwable { 190 count++; 191 return methodInvocation.proceed(); 192 } 193 } 194 195 static class DoubleInterceptor implements MethodInterceptor { 196 invoke(MethodInvocation methodInvocation)197 public Object invoke(MethodInvocation methodInvocation) throws Throwable { 198 methodInvocation.proceed(); 199 return methodInvocation.proceed(); 200 } 201 } 202 203 static class Counter { 204 int count; inc()205 void inc() { 206 count++; 207 } 208 } 209 } 210