ratpack.guice.internal.DefaultGuiceBackedHandlerFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ratpack-guice Show documentation
Show all versions of ratpack-guice Show documentation
Integration with Google Guice for Ratpack applications - https://code.google.com/p/google-guice/
/*
* Copyright 2013 the original author or authors.
*
* 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 ratpack.guice.internal;
import com.google.common.collect.ImmutableList;
import com.google.inject.Binder;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.util.Modules;
import io.netty.buffer.ByteBuf;
import ratpack.func.Action;
import ratpack.func.Factory;
import ratpack.func.Transformer;
import ratpack.guice.GuiceBackedHandlerFactory;
import ratpack.guice.HandlerDecoratingModule;
import ratpack.guice.ModuleRegistry;
import ratpack.handling.Handler;
import ratpack.handling.Handlers;
import ratpack.handling.internal.ClientErrorForwardingHandler;
import ratpack.handling.internal.FactoryHandler;
import ratpack.launch.LaunchConfig;
import ratpack.registry.NotInRegistryException;
import ratpack.reload.internal.ClassUtil;
import ratpack.reload.internal.ReloadableFileBackedFactory;
import javax.inject.Provider;
import java.io.File;
import java.nio.file.Path;
import java.util.*;
import static ratpack.util.ExceptionUtils.uncheck;
public class DefaultGuiceBackedHandlerFactory implements GuiceBackedHandlerFactory {
private final LaunchConfig launchConfig;
public DefaultGuiceBackedHandlerFactory(LaunchConfig launchConfig) {
this.launchConfig = launchConfig;
}
public Handler create(final Action super ModuleRegistry> modulesAction, final Transformer super Module, ? extends Injector> moduleTransformer, final Transformer super Injector, ? extends Handler> injectorTransformer) throws Exception {
if (launchConfig.isReloadable()) {
File classFile = ClassUtil.getClassFile(modulesAction);
if (classFile != null) {
Factory factory = new ReloadableFileBackedFactory<>(classFile.toPath(), true, new ReloadableFileBackedFactory.Producer() {
@Override
public InjectorBindingHandler produce(Path file, ByteBuf bytes) throws Exception {
return doCreate(modulesAction, moduleTransformer, injectorTransformer);
}
});
return new FactoryHandler(factory);
}
}
return doCreate(modulesAction, moduleTransformer, injectorTransformer);
}
private InjectorBindingHandler doCreate(Action super ModuleRegistry> modulesAction, Transformer super Module, ? extends Injector> moduleTransformer, Transformer super Injector, ? extends Handler> injectorTransformer) throws Exception {
DefaultModuleRegistry moduleRegistry = new DefaultModuleRegistry(launchConfig);
registerDefaultModules(moduleRegistry);
try {
modulesAction.execute(moduleRegistry);
} catch (Exception e) {
throw uncheck(e);
}
Module masterModule = null;
List extends Module> modules = moduleRegistry.getModules();
for (Module module : modules) {
if (masterModule == null) {
masterModule = module;
} else {
masterModule = Modules.override(masterModule).with(module);
}
}
Injector injector = moduleTransformer.transform(masterModule);
List> init = moduleRegistry.init;
for (Action initAction : init) {
initAction.execute(injector);
}
Handler decorated = injectorTransformer.transform(injector);
List modulesReversed = new ArrayList<>(modules);
Collections.reverse(modulesReversed);
for (Module module : modulesReversed) {
if (module instanceof HandlerDecoratingModule) {
decorated = ((HandlerDecoratingModule) module).decorate(injector, decorated);
}
}
decorated = Handlers.chain(decorateHandler(decorated), new ClientErrorForwardingHandler(404));
return new InjectorBindingHandler(injector, decorated);
}
protected Handler decorateHandler(Handler handler) {
return handler;
}
protected void registerDefaultModules(ModuleRegistry moduleRegistry) {
moduleRegistry.register(new DefaultRatpackModule(launchConfig));
}
private static class DefaultModuleRegistry implements ModuleRegistry {
private final Map, Module> modules = new LinkedHashMap<>();
private final LaunchConfig launchConfig;
private final LinkedList> actions = new LinkedList<>();
private final LinkedList> init = new LinkedList<>();
public DefaultModuleRegistry(LaunchConfig launchConfig) {
this.launchConfig = launchConfig;
}
public LaunchConfig getLaunchConfig() {
return launchConfig;
}
public void bind(final Class> type) {
actions.add(new Action() {
public void execute(Binder binder) {
binder.bind(type);
}
});
}
public void bind(final Class publicType, final Class extends T> implType) {
actions.add(new Action() {
public void execute(Binder binder) {
binder.bind(publicType).to(implType);
}
});
}
public void bind(final Class super T> publicType, final T instance) {
actions.add(new Action() {
public void execute(Binder binder) {
binder.bind(publicType).toInstance(instance);
}
});
}
public void bind(final T instance) {
@SuppressWarnings("unchecked") final
Class type = (Class) instance.getClass();
actions.add(new Action() {
public void execute(Binder binder) {
binder.bind(type).toInstance(instance);
}
});
}
public void provider(final Class publicType, final Class extends Provider extends T>> providerType) {
actions.add(new Action() {
public void execute(Binder binder) {
binder.bind(publicType).toProvider(providerType);
}
});
}
@SuppressWarnings("unchecked")
public void register(Module module) {
register((Class) module.getClass(), module);
}
@Override
public void registerLazy(Class type, Factory extends O> factory) {
register(type, factory.create());
}
public void register(Class type, O module) {
if (modules.containsKey(type)) {
Object existing = modules.get(type);
throw new IllegalArgumentException(String.format("Module '%s' is already registered with type '%s' (attempting to register '%s')", existing, type, module));
}
modules.put(type, module);
}
public T get(Class moduleType) {
@SuppressWarnings("SuspiciousMethodCalls") Module module = modules.get(moduleType);
if (module == null) {
throw new NotInRegistryException(moduleType);
}
return moduleType.cast(module);
}
@Override
public List getAll(Class type) {
ImmutableList.Builder builder = ImmutableList.builder();
for (Module module : modules.values()) {
if (type.isInstance(module)) {
@SuppressWarnings("unchecked") O cast = (O) module;
builder.add(cast);
}
}
return builder.build();
}
public O maybeGet(Class type) {
@SuppressWarnings("SuspiciousMethodCalls") Module module = modules.get(type);
if (module == null) {
return null;
}
return type.cast(module);
}
public void remove(Class moduleType) {
if (!modules.containsKey(moduleType)) {
throw new NotInRegistryException(moduleType);
}
modules.remove(moduleType);
}
private List getModules() {
return ImmutableList.builder()
.addAll(modules.values())
.add(createOverrideModule())
.build();
}
private Module createOverrideModule() {
return new Module() {
public void configure(Binder binder) {
for (Action binderAction : actions) {
try {
binderAction.execute(binder);
} catch (Exception e) {
throw uncheck(e);
}
}
}
};
}
@Override
public void init(Action action) {
init.add(action);
}
@Override
public void init(final Class extends Runnable> clazz) {
init.add(new Action() {
@Override
public void execute(Injector injector) throws Exception {
injector.getInstance(clazz).run();
}
});
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy