/*
* Copyright 2014-2016 Squarespace, 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.squarespace.jersey2.guice;
import java.util.concurrent.atomic.AtomicReference;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.api.ServiceLocatorFactory;
import org.glassfish.hk2.api.ServiceLocatorListener;
import org.glassfish.hk2.extension.ServiceLocatorGenerator;
import org.glassfish.hk2.internal.ServiceLocatorFactoryImpl;
/**
* This is an alternative to using the {@link GuiceServiceLocatorGeneratorStub} SPI.
*
* The idea is two swap out the {@link ServiceLocatorFactory#getInstance()} value
* and then pass our own {@link ServiceLocatorGenerator} into the {@code create(...)}
* methods instead of letting {@link ServiceLocatorFactoryImpl} pick one via SPI.
*/
class GuiceServiceLocatorFactory extends ServiceLocatorFactory {
private final AtomicReference<ServiceLocatorGenerator> generatorRef
= new AtomicReference<>();
private final ServiceLocatorFactory factory;
public GuiceServiceLocatorFactory(ServiceLocatorFactory factory) {
this.factory = factory;
}
public ServiceLocatorGenerator install(ServiceLocatorGenerator generator) {
return generatorRef.getAndSet(generator);
}
public ServiceLocatorGenerator get() {
return generatorRef.get();
}
@Override
public ServiceLocator create(String name) {
return create(name, null);
}
@Override
public ServiceLocator create(String name, ServiceLocator parent) {
return create(name, parent, null);
}
@Override
public ServiceLocator create(String name, ServiceLocator parent,
ServiceLocatorGenerator generator) {
return create(name, parent, generator, CreatePolicy.RETURN);
}
@Override
public ServiceLocator create(String name, ServiceLocator parent,
ServiceLocatorGenerator generator,
CreatePolicy policy) {
// NOTE: A non-null generator would be a bit unexpected here. It'd mean
// that something else is attempting to pass one in and it's no longer
// clear what's supposed to happen. We're going to respect it but it's
// most likely wrong. But speaking strictly in terms of Jersey please see
// Injections#_createLocator(...) which calls this method with a null arg.
if (generator == null) {
generator = generatorRef.get();
}
if (generator == null) {
throw new IllegalStateException("There is no ServiceLocatorGenerator installed.");
}
return factory.create(name, parent, generator, policy);
}
@Override
public ServiceLocator find(String name) {
return factory.find(name);
}
@Override
public void destroy(String name) {
factory.destroy(name);
}
@Override
public void destroy(ServiceLocator locator) {
factory.destroy(locator);
}
@Override
public void addListener(ServiceLocatorListener listener) {
factory.addListener(listener);
}
@Override
public void removeListener(ServiceLocatorListener listener) {
factory.removeListener(listener);
}
}