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
17package com.googlecode.guice.bundle;
18
19import static com.google.inject.name.Names.named;
20
21import com.google.inject.AbstractModule;
22import com.google.inject.Guice;
23import com.google.inject.Inject;
24import com.google.inject.Injector;
25import com.google.inject.Key;
26import com.google.inject.matcher.AbstractMatcher;
27
28import org.osgi.framework.Bundle;
29import org.osgi.framework.BundleActivator;
30import org.osgi.framework.BundleContext;
31import org.osgi.framework.BundleException;
32
33import java.lang.reflect.Method;
34import java.lang.reflect.Modifier;
35import 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
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