package service; import javax.jcr.Credentials; import javax.jcr.Repository; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.SimpleCredentials; import javax.naming.InitialContext; import javax.naming.NamingException; import models.User; import notification.EmailNotifier; import notification.EmailNotifierImpl; import notification.Notifier; import notification.NotifierImpl; import org.apache.jackrabbit.core.TransientRepository; import org.jcrom.Jcrom; import play.Application; import play.Plugin; import play.api.libs.JNDI; import play.libs.Akka; import play.libs.F; import providers.CacheableUserProvider; import providers.CacheableUserProviderImpl; import providers.JackrabbitEmailPasswordAuthProvider; import service.filestore.CommentStore; import service.filestore.CommentStoreImpl; import service.filestore.FileStore; import service.filestore.FileStoreImpl; import service.filestore.FlagStore; import akka.actor.TypedActor; import akka.actor.TypedProps; import akka.japi.Creator; import charts.builder.CachedChartBuilder; import charts.builder.ChartBuilder; import charts.builder.ChartCache; import charts.builder.ChartCacheImpl; import charts.builder.DataSourceFactory; import charts.builder.DefaultChartBuilder; import charts.builder.FileStoreDataSourceFactory; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; import com.google.inject.Provides; import com.google.inject.Singleton; import com.wingnest.play2.jackrabbit.Jcr; import com.wingnest.play2.jackrabbit.plugin.ConfigConsts; import email.Email; import email.EmailImpl; public class GuiceInjectionPlugin extends Plugin { private final Application application; private Injector injector = null; public GuiceInjectionPlugin(Application application) { this.application = application; } @Override public void onStart() { injector = createInjector(); } @Override public void onStop() { injector = null; } public Injector getInjector() { return injector; } public static Injector getInjector(Application application) { return application.plugin(GuiceInjectionPlugin.class).getInjector(); } private Injector createInjector() { final Jcrom jcrom = buildJcrom(); final Credentials adminCredentials = new SimpleCredentials( cfgStr(ConfigConsts.CONF_JCR_USERID), cfgStr(ConfigConsts.CONF_JCR_PASSWORD).toCharArray()); registerRepoInJNDI(Jcr.getRepository()); final Module eventManagerModule = new AbstractModule() { @Override protected void configure() { final EventManager em = TypedActor.get(Akka.system()).typedActorOf( new TypedProps<EventManagerImpl>( EventManager.class, EventManagerImpl.class)); bind(EventManager.class).toInstance(em); } }; final JcrSessionFactory sessionFactory = new JcrSessionFactory() { @Override public Session newAdminSession() { try { return Jcr.getRepository().login(adminCredentials); } catch (RepositoryException e) { throw new RuntimeException(); } } }; final Module sessionModule = new AbstractModule() { protected final TransientRepository repository = new TransientRepository(); @Override protected void configure() { bind(Jcrom.class).toInstance(jcrom); bind(JcrSessionFactory.class).toInstance(sessionFactory); bind(FileStore.class) .to(FileStoreImpl.class) .asEagerSingleton(); sessionFactory.inSession(new F.Function<Session, Session>() { @Override public Session apply(Session session) throws Throwable { bind(FlagStore.class) .toInstance(new FlagStore(jcrom, session)); bind(CommentStore.class) .toInstance(new CommentStoreImpl(jcrom, session)); return session; } }); bind(CacheableUserProvider.class) .to(CacheableUserProviderImpl.class) .in(Singleton.class); bind(DataSourceFactory.class) .to(FileStoreDataSourceFactory.class) .in(Singleton.class); bind(Email.class).to(EmailImpl.class); } }; final Module pluginModule = new AbstractModule() { @Override protected void configure() {} @Provides SimpleUserServicePlugin getUserService() { return application.plugin(SimpleUserServicePlugin.class); } @Provides JackrabbitEmailPasswordAuthProvider getEmailPasswordAuthProvider() { return application.plugin(JackrabbitEmailPasswordAuthProvider.class); } }; final Injector intermediateInjector = Guice.createInjector( eventManagerModule, pluginModule, sessionModule); final Module chartBuilderModule = new AbstractModule() { @Override protected void configure() { final Creator<ChartCache> ccc = new Creator<ChartCache>() { private static final long serialVersionUID = 1L; @Override public ChartCache create() { final EventManager em = intermediateInjector.getInstance(EventManager.class); final DefaultChartBuilder dcb = new DefaultChartBuilder( intermediateInjector.getInstance(DataSourceFactory.class)); return new ChartCacheImpl(dcb, em); } }; final ChartCache cc = TypedActor.get(Akka.system()).typedActorOf( new TypedProps<ChartCache>( ChartCache.class, ccc)); bind(ChartCache.class).toInstance(cc); bind(ChartBuilder.class) .to(CachedChartBuilder.class) .in(Singleton.class); } }; final Module notificationModule = new AbstractModule() { @Override protected void configure() { bind(Notifier.class).toInstance(typedActor( intermediateInjector, Notifier.class, NotifierImpl.class)); bind(EmailNotifier.class).toInstance(typedActor( intermediateInjector, EmailNotifier.class, EmailNotifierImpl.class)); } }; return intermediateInjector.createChildInjector(chartBuilderModule, notificationModule); } private <T> T typedActor(final Injector injector, final Class<T> iface, final Class <? extends T> impl) { return TypedActor.get(Akka.system()).typedActorOf( new TypedProps<T>(iface, new Creator<T>() { @Override public T create() { return injector.getInstance(impl); } })); } private void registerRepoInJNDI(Repository repo) { try { InitialContext ic = JNDI.initialContext(); ic.rebind("/jackrabbit", repo); } catch (NamingException ne) { throw new RuntimeException(ne); } } private Jcrom buildJcrom() { final Jcrom jcrom = new Jcrom(false, true); jcrom.map(User.class); jcrom.map(models.Comment.class); jcrom.map(models.Flag.class); jcrom.map(models.Notification.class); jcrom.map(models.filestore.File.class); jcrom.map(models.filestore.Folder.class); return jcrom; } private String cfgStr(String key) { return application.configuration().getString(key); } }