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@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 
AA()60     public AA() {}
61 
setA(Undefined undefined)62     @Inject public void setA(Undefined undefined) {}
63 
setB(Undefined undefined)64     @Inject protected void setB(Undefined undefined) {}
65 
setC(Undefined undefined)66     @Inject void setC(Undefined undefined) {}
67 
setD(Undefined undefined)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 
AB()82     public AB() {}
83 
setA(Undefined undefined)84     @Inject public void setA(Undefined undefined) {}
85 
setB(Undefined undefined)86     @Inject protected void setB(Undefined undefined) {}
87 
setC(Undefined undefined)88     @Inject void setC(Undefined undefined) {}
89 
setD(Undefined undefined)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 
AC()104     public AC() {}
105 
setA(Undefined undefined)106     @Inject public void setA(Undefined undefined) {}
107 
setB(Undefined undefined)108     @Inject protected void setB(Undefined undefined) {}
109 
setC(Undefined undefined)110     @Inject void setC(Undefined undefined) {}
111 
setD(Undefined undefined)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 
AD()126     public AD() {}
127 
setA(Undefined undefined)128     @Inject public void setA(Undefined undefined) {}
129 
setB(Undefined undefined)130     @Inject protected void setB(Undefined undefined) {}
131 
setC(Undefined undefined)132     @Inject void setC(Undefined undefined) {}
133 
setD(Undefined undefined)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 
BA()148     protected BA() {}
149 
setA(Undefined undefined)150     @Inject public void setA(Undefined undefined) {}
151 
setB(Undefined undefined)152     @Inject protected void setB(Undefined undefined) {}
153 
setC(Undefined undefined)154     @Inject void setC(Undefined undefined) {}
155 
setD(Undefined undefined)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 
BB()170     protected BB() {}
171 
setA(Undefined undefined)172     @Inject public void setA(Undefined undefined) {}
173 
setB(Undefined undefined)174     @Inject protected void setB(Undefined undefined) {}
175 
setC(Undefined undefined)176     @Inject void setC(Undefined undefined) {}
177 
setD(Undefined undefined)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 
BC()192     protected BC() {}
193 
setA(Undefined undefined)194     @Inject public void setA(Undefined undefined) {}
195 
setB(Undefined undefined)196     @Inject protected void setB(Undefined undefined) {}
197 
setC(Undefined undefined)198     @Inject void setC(Undefined undefined) {}
199 
setD(Undefined undefined)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 
BD()214     protected BD() {}
215 
setA(Undefined undefined)216     @Inject public void setA(Undefined undefined) {}
217 
setB(Undefined undefined)218     @Inject protected void setB(Undefined undefined) {}
219 
setC(Undefined undefined)220     @Inject void setC(Undefined undefined) {}
221 
setD(Undefined undefined)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 
CA()236     CA() {}
237 
setA(Undefined undefined)238     @Inject public void setA(Undefined undefined) {}
239 
setB(Undefined undefined)240     @Inject protected void setB(Undefined undefined) {}
241 
setC(Undefined undefined)242     @Inject void setC(Undefined undefined) {}
243 
setD(Undefined undefined)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 
CB()258     CB() {}
259 
setA(Undefined undefined)260     @Inject public void setA(Undefined undefined) {}
261 
setB(Undefined undefined)262     @Inject protected void setB(Undefined undefined) {}
263 
setC(Undefined undefined)264     @Inject void setC(Undefined undefined) {}
265 
setD(Undefined undefined)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 
CC()280     CC() {}
281 
setA(Undefined undefined)282     @Inject public void setA(Undefined undefined) {}
283 
setB(Undefined undefined)284     @Inject protected void setB(Undefined undefined) {}
285 
setC(Undefined undefined)286     @Inject void setC(Undefined undefined) {}
287 
setD(Undefined undefined)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 
CD()302     CD() {}
303 
setA(Undefined undefined)304     @Inject public void setA(Undefined undefined) {}
305 
setB(Undefined undefined)306     @Inject protected void setB(Undefined undefined) {}
307 
setC(Undefined undefined)308     @Inject void setC(Undefined undefined) {}
309 
setD(Undefined undefined)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 
DA()324     @Inject private DA() {}
325 
setA(Undefined undefined)326     @Inject public void setA(Undefined undefined) {}
327 
setB(Undefined undefined)328     @Inject protected void setB(Undefined undefined) {}
329 
setC(Undefined undefined)330     @Inject void setC(Undefined undefined) {}
331 
setD(Undefined undefined)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 
DB()346     @Inject private DB() {}
347 
setA(Undefined undefined)348     @Inject public void setA(Undefined undefined) {}
349 
setB(Undefined undefined)350     @Inject protected void setB(Undefined undefined) {}
351 
setC(Undefined undefined)352     @Inject void setC(Undefined undefined) {}
353 
setD(Undefined undefined)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 
DC()368     @Inject private DC() {}
369 
setA(Undefined undefined)370     @Inject public void setA(Undefined undefined) {}
371 
setB(Undefined undefined)372     @Inject protected void setB(Undefined undefined) {}
373 
setC(Undefined undefined)374     @Inject void setC(Undefined undefined) {}
375 
setD(Undefined undefined)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 
DD()390     private DD() {}
391 
setA(Undefined undefined)392     @Inject public void setA(Undefined undefined) {}
393 
setB(Undefined undefined)394     @Inject protected void setB(Undefined undefined) {}
395 
setC(Undefined undefined)396     @Inject void setC(Undefined undefined) {}
397 
setD(Undefined undefined)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 
TestModule(Bundle bundle)421     TestModule(Bundle bundle) {
422       this.bundle = bundle;
423     }
424 
configure()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 {
configure()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
start(BundleContext context)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
stop(BundleContext context)510   public void stop(BundleContext context) {}
511 }
512