Home | History | Annotate | Download | only in bundle
      1 /**
      2  * Copyright (C) 2009 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.googlecode.guice.bundle;
     18 
     19 import static com.google.inject.name.Names.named;
     20 
     21 import com.google.inject.AbstractModule;
     22 import com.google.inject.Guice;
     23 import com.google.inject.Inject;
     24 import com.google.inject.Injector;
     25 import com.google.inject.Key;
     26 import com.google.inject.matcher.AbstractMatcher;
     27 
     28 import org.osgi.framework.Bundle;
     29 import org.osgi.framework.BundleActivator;
     30 import org.osgi.framework.BundleContext;
     31 import org.osgi.framework.BundleException;
     32 
     33 import java.lang.reflect.Method;
     34 import java.lang.reflect.Modifier;
     35 import java.util.Random;
     36 
     37 /**
     38  * Test Guice from inside an OSGi bundle activator.
     39  *
     40  * @author mcculls (at) gmail.com (Stuart McCulloch)
     41  */
     42 @SuppressWarnings("unused") public class OSGiTestActivator
     43     implements BundleActivator {
     44 
     45   // varying visibilities to test our code-generation support
     46 
     47   public static class Undefined {}
     48 
     49   public interface A {}
     50 
     51   protected interface B {}
     52 
     53   interface C {}
     54 
     55   private interface D {}
     56 
     57   public static class AA
     58       implements A {
     59 
     60     public AA() {}
     61 
     62     @Inject public void setA(Undefined undefined) {}
     63 
     64     @Inject protected void setB(Undefined undefined) {}
     65 
     66     @Inject void setC(Undefined undefined) {}
     67 
     68     @Inject private void setD(Undefined undefined) {}
     69 
     70     @Inject public Undefined a;
     71 
     72     @Inject protected Undefined b;
     73 
     74     @Inject Undefined c;
     75 
     76     @Inject private Undefined d;
     77   }
     78 
     79   protected static class AB
     80       implements A {
     81 
     82     public AB() {}
     83 
     84     @Inject public void setA(Undefined undefined) {}
     85 
     86     @Inject protected void setB(Undefined undefined) {}
     87 
     88     @Inject void setC(Undefined undefined) {}
     89 
     90     @Inject private void setD(Undefined undefined) {}
     91 
     92     @Inject public Undefined a;
     93 
     94     @Inject protected Undefined b;
     95 
     96     @Inject Undefined c;
     97 
     98     @Inject private Undefined d;
     99   }
    100 
    101   static class AC
    102       implements A {
    103 
    104     public AC() {}
    105 
    106     @Inject public void setA(Undefined undefined) {}
    107 
    108     @Inject protected void setB(Undefined undefined) {}
    109 
    110     @Inject void setC(Undefined undefined) {}
    111 
    112     @Inject private void setD(Undefined undefined) {}
    113 
    114     @Inject public Undefined a;
    115 
    116     @Inject protected Undefined b;
    117 
    118     @Inject Undefined c;
    119 
    120     @Inject private Undefined d;
    121   }
    122 
    123   private static class AD
    124       implements A {
    125 
    126     public AD() {}
    127 
    128     @Inject public void setA(Undefined undefined) {}
    129 
    130     @Inject protected void setB(Undefined undefined) {}
    131 
    132     @Inject void setC(Undefined undefined) {}
    133 
    134     @Inject private void setD(Undefined undefined) {}
    135 
    136     @Inject public Undefined a;
    137 
    138     @Inject protected Undefined b;
    139 
    140     @Inject Undefined c;
    141 
    142     @Inject private Undefined d;
    143   }
    144 
    145   public static class BA
    146       implements B {
    147 
    148     protected BA() {}
    149 
    150     @Inject public void setA(Undefined undefined) {}
    151 
    152     @Inject protected void setB(Undefined undefined) {}
    153 
    154     @Inject void setC(Undefined undefined) {}
    155 
    156     @Inject private void setD(Undefined undefined) {}
    157 
    158     @Inject public Undefined a;
    159 
    160     @Inject protected Undefined b;
    161 
    162     @Inject Undefined c;
    163 
    164     @Inject private Undefined d;
    165   }
    166 
    167   protected static class BB
    168       implements B {
    169 
    170     protected BB() {}
    171 
    172     @Inject public void setA(Undefined undefined) {}
    173 
    174     @Inject protected void setB(Undefined undefined) {}
    175 
    176     @Inject void setC(Undefined undefined) {}
    177 
    178     @Inject private void setD(Undefined undefined) {}
    179 
    180     @Inject public Undefined a;
    181 
    182     @Inject protected Undefined b;
    183 
    184     @Inject Undefined c;
    185 
    186     @Inject private Undefined d;
    187   }
    188 
    189   static class BC
    190       implements B {
    191 
    192     protected BC() {}
    193 
    194     @Inject public void setA(Undefined undefined) {}
    195 
    196     @Inject protected void setB(Undefined undefined) {}
    197 
    198     @Inject void setC(Undefined undefined) {}
    199 
    200     @Inject private void setD(Undefined undefined) {}
    201 
    202     @Inject public Undefined a;
    203 
    204     @Inject protected Undefined b;
    205 
    206     @Inject Undefined c;
    207 
    208     @Inject private Undefined d;
    209   }
    210 
    211   private static class BD
    212       implements B {
    213 
    214     protected BD() {}
    215 
    216     @Inject public void setA(Undefined undefined) {}
    217 
    218     @Inject protected void setB(Undefined undefined) {}
    219 
    220     @Inject void setC(Undefined undefined) {}
    221 
    222     @Inject private void setD(Undefined undefined) {}
    223 
    224     @Inject public Undefined a;
    225 
    226     @Inject protected Undefined b;
    227 
    228     @Inject Undefined c;
    229 
    230     @Inject private Undefined d;
    231   }
    232 
    233   public static class CA
    234       implements C {
    235 
    236     CA() {}
    237 
    238     @Inject public void setA(Undefined undefined) {}
    239 
    240     @Inject protected void setB(Undefined undefined) {}
    241 
    242     @Inject void setC(Undefined undefined) {}
    243 
    244     @Inject private void setD(Undefined undefined) {}
    245 
    246     @Inject public Undefined a;
    247 
    248     @Inject protected Undefined b;
    249 
    250     @Inject Undefined c;
    251 
    252     @Inject private Undefined d;
    253   }
    254 
    255   protected static class CB
    256       implements C {
    257 
    258     CB() {}
    259 
    260     @Inject public void setA(Undefined undefined) {}
    261 
    262     @Inject protected void setB(Undefined undefined) {}
    263 
    264     @Inject void setC(Undefined undefined) {}
    265 
    266     @Inject private void setD(Undefined undefined) {}
    267 
    268     @Inject public Undefined a;
    269 
    270     @Inject protected Undefined b;
    271 
    272     @Inject Undefined c;
    273 
    274     @Inject private Undefined d;
    275   }
    276 
    277   static class CC
    278       implements C {
    279 
    280     CC() {}
    281 
    282     @Inject public void setA(Undefined undefined) {}
    283 
    284     @Inject protected void setB(Undefined undefined) {}
    285 
    286     @Inject void setC(Undefined undefined) {}
    287 
    288     @Inject private void setD(Undefined undefined) {}
    289 
    290     @Inject public Undefined a;
    291 
    292     @Inject protected Undefined b;
    293 
    294     @Inject Undefined c;
    295 
    296     @Inject private Undefined d;
    297   }
    298 
    299   private static class CD
    300       implements C {
    301 
    302     CD() {}
    303 
    304     @Inject public void setA(Undefined undefined) {}
    305 
    306     @Inject protected void setB(Undefined undefined) {}
    307 
    308     @Inject void setC(Undefined undefined) {}
    309 
    310     @Inject private void setD(Undefined undefined) {}
    311 
    312     @Inject public Undefined a;
    313 
    314     @Inject protected Undefined b;
    315 
    316     @Inject Undefined c;
    317 
    318     @Inject private Undefined d;
    319   }
    320 
    321   public static class DA
    322       implements D {
    323 
    324     @Inject private DA() {}
    325 
    326     @Inject public void setA(Undefined undefined) {}
    327 
    328     @Inject protected void setB(Undefined undefined) {}
    329 
    330     @Inject void setC(Undefined undefined) {}
    331 
    332     @Inject private void setD(Undefined undefined) {}
    333 
    334     @Inject public Undefined a;
    335 
    336     @Inject protected Undefined b;
    337 
    338     @Inject Undefined c;
    339 
    340     @Inject private Undefined d;
    341   }
    342 
    343   protected static class DB
    344       implements D {
    345 
    346     @Inject private DB() {}
    347 
    348     @Inject public void setA(Undefined undefined) {}
    349 
    350     @Inject protected void setB(Undefined undefined) {}
    351 
    352     @Inject void setC(Undefined undefined) {}
    353 
    354     @Inject private void setD(Undefined undefined) {}
    355 
    356     @Inject public Undefined a;
    357 
    358     @Inject protected Undefined b;
    359 
    360     @Inject Undefined c;
    361 
    362     @Inject private Undefined d;
    363   }
    364 
    365   static class DC
    366       implements D {
    367 
    368     @Inject private DC() {}
    369 
    370     @Inject public void setA(Undefined undefined) {}
    371 
    372     @Inject protected void setB(Undefined undefined) {}
    373 
    374     @Inject void setC(Undefined undefined) {}
    375 
    376     @Inject private void setD(Undefined undefined) {}
    377 
    378     @Inject public Undefined a;
    379 
    380     @Inject protected Undefined b;
    381 
    382     @Inject Undefined c;
    383 
    384     @Inject private Undefined d;
    385   }
    386 
    387   private static class DD
    388       implements D {
    389 
    390     private DD() {}
    391 
    392     @Inject public void setA(Undefined undefined) {}
    393 
    394     @Inject protected void setB(Undefined undefined) {}
    395 
    396     @Inject void setC(Undefined undefined) {}
    397 
    398     @Inject private void setD(Undefined undefined) {}
    399 
    400     @Inject public Undefined a;
    401 
    402     @Inject protected Undefined b;
    403 
    404     @Inject Undefined c;
    405 
    406     @Inject private Undefined d;
    407   }
    408 
    409   enum Visibility {
    410     PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE
    411   }
    412 
    413   static final Class<?>[] TEST_CLAZZES = {A.class, B.class, C.class, D.class};
    414 
    415   // registers all the class combinations
    416   static class TestModule
    417       extends AbstractModule {
    418 
    419     final Bundle bundle;
    420 
    421     TestModule(Bundle bundle) {
    422       this.bundle = bundle;
    423     }
    424 
    425     @Override @SuppressWarnings("unchecked") protected void configure() {
    426       for (Class<?> api : TEST_CLAZZES) {
    427         for (Visibility visibility : Visibility.values()) {
    428           try {
    429 
    430             // this registers: A + PUBLIC -> AA, A + PROTECTED -> AB, etc...
    431             String suffix = TEST_CLAZZES[visibility.ordinal()].getSimpleName();
    432             Class imp = bundle.loadClass(api.getName() + suffix);
    433             bind(api).annotatedWith(named(visibility.name())).to(imp);
    434 
    435           } catch (ClassNotFoundException e) {
    436             throw new RuntimeException("Unable to load test class", e);
    437           }
    438         }
    439       }
    440     }
    441   }
    442 
    443 /*if[AOP]*/
    444   // applies method-interception to classes with enough visibility
    445   static class InterceptorModule
    446       extends AbstractModule {
    447     @Override protected void configure() {
    448       bindInterceptor(new AbstractMatcher<Class<?>>() {
    449         public boolean matches(Class<?> clazz) {
    450           try {
    451 
    452             // the class and constructor must be visible
    453             int clazzModifiers = clazz.getModifiers();
    454             int ctorModifiers = clazz.getConstructor().getModifiers();
    455             return (clazzModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0
    456                 && (ctorModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0;
    457 
    458           } catch (NoSuchMethodException e) {
    459             return false;
    460           }
    461         }
    462       }, new AbstractMatcher<Method>() {
    463         public boolean matches(Method method) {
    464 
    465           // the intercepted method must also be visible
    466           int methodModifiers = method.getModifiers();
    467           return (methodModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0;
    468 
    469         }
    470       }, new org.aopalliance.intercept.MethodInterceptor() {
    471         public Object invoke(org.aopalliance.intercept.MethodInvocation mi)
    472             throws Throwable {
    473 
    474           return mi.proceed();
    475         }
    476       });
    477     }
    478   }
    479 /*end[AOP]*/
    480 
    481   // called from OSGi when bundle starts
    482   public void start(BundleContext context)
    483       throws BundleException {
    484 
    485     final Bundle bundle = context.getBundle();
    486 
    487     Injector injector = Guice.createInjector(new TestModule(bundle));
    488 /*if[AOP]*/
    489     Injector aopInjector = Guice.createInjector(new TestModule(bundle), new InterceptorModule());
    490 /*end[AOP]*/
    491 
    492     // test code-generation support
    493     for (Class<?> api : TEST_CLAZZES) {
    494       for (Visibility vis : Visibility.values()) {
    495         injector.getInstance(Key.get(api, named(vis.name())));
    496 /*if[AOP]*/
    497         aopInjector.getInstance(Key.get(api, named(vis.name())));
    498 /*end[AOP]*/
    499       }
    500     }
    501 
    502     // test injection of system class (issue 343)
    503     injector.getInstance(Random.class);
    504 /*if[AOP]*/
    505     aopInjector.getInstance(Random.class);
    506 /*end[AOP]*/
    507   }
    508 
    509   // called from OSGi when bundle stops
    510   public void stop(BundleContext context) {}
    511 }
    512