blob: 67caee50627751671fed4ce6a64ee065ffdb2c4f [file] [log] [blame]
/**
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.guice.bundle;
import static com.google.inject.name.Names.named;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.matcher.AbstractMatcher;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Random;
/**
* Test Guice from inside an OSGi bundle activator.
*
* @author mcculls@gmail.com (Stuart McCulloch)
*/
@SuppressWarnings("unused") public class OSGiTestActivator
implements BundleActivator {
// varying visibilities to test our code-generation support
public static class Undefined {}
public interface A {}
protected interface B {}
interface C {}
private interface D {}
public static class AA
implements A {
public AA() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
protected static class AB
implements A {
public AB() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
static class AC
implements A {
public AC() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
private static class AD
implements A {
public AD() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
public static class BA
implements B {
protected BA() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
protected static class BB
implements B {
protected BB() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
static class BC
implements B {
protected BC() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
private static class BD
implements B {
protected BD() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
public static class CA
implements C {
CA() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
protected static class CB
implements C {
CB() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
static class CC
implements C {
CC() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
private static class CD
implements C {
CD() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
public static class DA
implements D {
@Inject private DA() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
protected static class DB
implements D {
@Inject private DB() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
static class DC
implements D {
@Inject private DC() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
private static class DD
implements D {
private DD() {}
@Inject public void setA(Undefined undefined) {}
@Inject protected void setB(Undefined undefined) {}
@Inject void setC(Undefined undefined) {}
@Inject private void setD(Undefined undefined) {}
@Inject public Undefined a;
@Inject protected Undefined b;
@Inject Undefined c;
@Inject private Undefined d;
}
enum Visibility {
PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE
}
static final Class<?>[] TEST_CLAZZES = {A.class, B.class, C.class, D.class};
// registers all the class combinations
static class TestModule
extends AbstractModule {
final Bundle bundle;
TestModule(Bundle bundle) {
this.bundle = bundle;
}
@Override @SuppressWarnings("unchecked") protected void configure() {
for (Class<?> api : TEST_CLAZZES) {
for (Visibility visibility : Visibility.values()) {
try {
// this registers: A + PUBLIC -> AA, A + PROTECTED -> AB, etc...
String suffix = TEST_CLAZZES[visibility.ordinal()].getSimpleName();
Class imp = bundle.loadClass(api.getName() + suffix);
bind(api).annotatedWith(named(visibility.name())).to(imp);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Unable to load test class", e);
}
}
}
}
}
/*if[AOP]*/
// applies method-interception to classes with enough visibility
static class InterceptorModule
extends AbstractModule {
@Override protected void configure() {
bindInterceptor(new AbstractMatcher<Class<?>>() {
public boolean matches(Class<?> clazz) {
try {
// the class and constructor must be visible
int clazzModifiers = clazz.getModifiers();
int ctorModifiers = clazz.getConstructor().getModifiers();
return (clazzModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0
&& (ctorModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0;
} catch (NoSuchMethodException e) {
return false;
}
}
}, new AbstractMatcher<Method>() {
public boolean matches(Method method) {
// the intercepted method must also be visible
int methodModifiers = method.getModifiers();
return (methodModifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0;
}
}, new org.aopalliance.intercept.MethodInterceptor() {
public Object invoke(org.aopalliance.intercept.MethodInvocation mi)
throws Throwable {
return mi.proceed();
}
});
}
}
/*end[AOP]*/
// called from OSGi when bundle starts
public void start(BundleContext context)
throws BundleException {
final Bundle bundle = context.getBundle();
Injector injector = Guice.createInjector(new TestModule(bundle));
/*if[AOP]*/
Injector aopInjector = Guice.createInjector(new TestModule(bundle), new InterceptorModule());
/*end[AOP]*/
// test code-generation support
for (Class<?> api : TEST_CLAZZES) {
for (Visibility vis : Visibility.values()) {
injector.getInstance(Key.get(api, named(vis.name())));
/*if[AOP]*/
aopInjector.getInstance(Key.get(api, named(vis.name())));
/*end[AOP]*/
}
}
// test injection of system class (issue 343)
injector.getInstance(Random.class);
/*if[AOP]*/
aopInjector.getInstance(Random.class);
/*end[AOP]*/
}
// called from OSGi when bundle stops
public void stop(BundleContext context) {}
}