/**
* Copyright (c) 2013-2016, The SeedStack authors <http://seedstack.org>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.seedstack.seed.rest.jersey2.internal;
import com.google.inject.Injector;
import org.glassfish.hk2.api.DynamicConfiguration;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.utilities.binding.ServiceBindingBuilder;
import org.glassfish.jersey.internal.inject.Injections;
import org.glassfish.jersey.server.spi.ComponentProvider;
import org.jvnet.hk2.guice.bridge.api.GuiceBridge;
import org.jvnet.hk2.guice.bridge.api.GuiceIntoHK2Bridge;
import org.seedstack.seed.SeedException;
import javax.servlet.ServletContext;
import javax.ws.rs.Path;
import javax.ws.rs.ext.Provider;
import java.util.Set;
public class GuiceComponentProvider implements ComponentProvider {
private ServiceLocator serviceLocator;
private Injector injector;
@Override
public void initialize(ServiceLocator locator) {
prepareGuiceHK2Bridge(locator);
}
private void prepareGuiceHK2Bridge(ServiceLocator locator) {
setServiceLocatorAndInjector(locator);
GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
GuiceIntoHK2Bridge guiceBridge = locator.getService(GuiceIntoHK2Bridge.class);
guiceBridge.bridgeGuiceInjector(injector);
}
private void setServiceLocatorAndInjector(ServiceLocator locator) {
this.serviceLocator = locator;
injector = (Injector) getServletContext().getAttribute(Injector.class.getName());
if (injector == null) {
throw SeedException.createNew(Jersey2ErrorCode.MISSING_INJECTOR);
}
}
private ServletContext getServletContext() {
ServletContext servletContext = serviceLocator.getService(ServletContext.class);
if (servletContext == null) {
throw SeedException.createNew(Jersey2ErrorCode.MISSING_SERVLET_CONTEXT);
}
return servletContext;
}
@SuppressWarnings("unchecked")
@Override
public boolean bind(Class<?> component, Set<Class<?>> providerContracts) {
boolean isBound = false;
if (isJaxRsClass(component)) {
registerBindingsInHK2(component, providerContracts);
isBound = true;
}
return isBound;
}
private boolean isJaxRsClass(Class<?> component) {
return component.isAnnotationPresent(Path.class) || component.isAnnotationPresent(Provider.class);
}
private void registerBindingsInHK2(Class<?> componentClass, Set<Class<?>> providerContracts) {
ServiceBindingBuilder componentBindingBuilder = getBindingBuilder(componentClass);
//noinspection unchecked
componentBindingBuilder.to(componentClass);
bindProviderContracts(componentBindingBuilder, providerContracts);
DynamicConfiguration dynamicConfiguration = Injections.getConfiguration(serviceLocator);
Injections.addBinding(componentBindingBuilder, dynamicConfiguration);
dynamicConfiguration.commit();
}
private ServiceBindingBuilder getBindingBuilder(Class<?> component) {
GuiceToHK2Factory guiceFactory = new GuiceToHK2Factory(component, injector, serviceLocator);
return Injections.newFactoryBinder(guiceFactory);
}
@SuppressWarnings("unchecked")
private void bindProviderContracts(ServiceBindingBuilder componentBindingBuilder, Set<Class<?>> providerContracts) {
if (providerContracts != null) {
for (Class<?> providerContract : providerContracts) {
componentBindingBuilder.to(providerContract);
}
}
}
@Override
public void done() {
}
}