package me.moodcat.core;
import java.io.File;
import java.lang.annotation.Annotation;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.Path;
import javax.ws.rs.ext.Provider;
import lombok.extern.slf4j.Slf4j;
import me.moodcat.backend.UnitOfWorkSchedulingServiceImpl;
import me.moodcat.backend.rooms.RoomBackend;
import me.moodcat.backend.rooms.RoomBackendModule;
import me.moodcat.database.DbModule;
import me.moodcat.database.entities.User;
import org.eclipse.jetty.util.component.LifeCycle;
import org.jboss.resteasy.plugins.guice.ext.JaxrsModule;
import org.reflections.Reflections;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.inject.Provides;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import com.google.inject.persist.PersistFilter;
import com.google.inject.servlet.RequestScoped;
import com.google.inject.servlet.ServletModule;
/**
* The MoodcatServletModule is the Dependency Injection module for the
* MoodCat base API service. It tells Google Guice which classes (and their
* dependencies) to instantiate.
*/
@Slf4j
public class MoodcatServletModule extends ServletModule {
private static final String API_PACKAGE_NAME = "me.moodcat.api";
private static final String MAPPER_PACKAGE_NAME = "me.moodcat.core.mappers";
private static final String FILTER_PACKAGE_NAME = "me.moodcat.api.filters";
private static final int THREAD_POOL_SIZE = 4;
private final App app;
/**
* The rootFolder that contains all resources.
*/
private final File rootFolder;
public MoodcatServletModule(final App app, final File rootFolder) {
this.app = app;
this.rootFolder = rootFolder;
}
@Override
protected void configureServlets() {
// Install the JaxrsModule to use Guice with Jax RS
this.install(new JaxrsModule());
// Ensure an ObjectMapper (json (de)serializer) is available at this point
this.requireBinding(ObjectMapper.class);
this.bindConstants();
// Bind the database module
this.bindDatabaseModule();
this.bindAPI();
this.install(new RoomBackendModule());
// Bind eager singletons
this.bind(UnitOfWorkSchedulingServiceImpl.class).asEagerSingleton();
this.bind(RoomBackend.class).asEagerSingleton();
}
private void bindConstants() {
// Provide a way to access the resources folder from other classes
this.bind(File.class).annotatedWith(Names.named("root.folder"))
.toInstance(this.rootFolder);
this.bindConstant().annotatedWith(Names.named("thread.pool.size")).to(THREAD_POOL_SIZE);
this.bind(LifeCycle.class).toInstance(this.app.getServer());
}
private void bindDatabaseModule() {
install(new DbModule());
filter("/*").through(PersistFilter.class);
requireBinding(EntityManager.class);
requireBinding(EntityManagerFactory.class);
}
private void bindAPI() {
this.bindClassesAnnotatedWithInPackage(API_PACKAGE_NAME, Path.class);
this.bindClassesAnnotatedWithInPackage(MAPPER_PACKAGE_NAME, Provider.class);
this.bindClassesAnnotatedWithInPackage(FILTER_PACKAGE_NAME, Provider.class);
}
private void bindClassesAnnotatedWithInPackage(final String packageName,
final Class<? extends Annotation> annotation) {
final Reflections reflections = new Reflections(packageName);
for (final Class<?> clazz : reflections.getTypesAnnotatedWith(annotation)) {
this.bind(clazz);
log.info("Registering class {}", clazz);
}
}
@Provides
@Named("current.user")
@RequestScoped
public User provideCurrentUser() {
throw new NotAuthorizedException("user id must be manually seeded");
}
}