Home | History | Annotate | Download | only in internal
      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 (at) google.com (Bob Lee)
     40  */
     41 public class ProxyFactoryTest extends TestCase {
     42 
     43   List<MethodAspect> aspects = Lists.newArrayList();
     44 
     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;
     63     public void invoke() {
     64       invoked = true;
     65     }
     66   }
     67 
     68   static class SimpleInterceptor implements MethodInterceptor {
     69 
     70     boolean invoked = false;
     71 
     72     public Object invoke(MethodInvocation methodInvocation) throws Throwable {
     73       invoked = true;
     74       return methodInvocation.proceed();
     75     }
     76   }
     77 
     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
    108     void foo() {
    109       fooCalled = true;
    110     }
    111   }
    112 
    113   static class Bar {
    114 
    115     boolean barCalled;
    116     void bar() {
    117       barCalled = true;
    118     }
    119 
    120     boolean interceptedCalled;
    121 
    122     @Intercept
    123     void intercepted() {
    124       interceptedCalled = true;
    125     }
    126   }
    127 
    128   @Retention(RetentionPolicy.RUNTIME)
    129   @interface Intercept {}
    130 
    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 
    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;
    162     @Inject public A(int i) {
    163       this.i = i;
    164     }
    165     public void a() {}
    166   }
    167 
    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 
    189     public Object invoke(MethodInvocation methodInvocation) throws Throwable {
    190       count++;
    191       return methodInvocation.proceed();
    192     }
    193   }
    194 
    195   static class DoubleInterceptor implements MethodInterceptor {
    196 
    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;
    205     void inc() {
    206       count++;
    207     }
    208   }
    209 }
    210