/*
* Copyright 2012 Netflix, 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.netflix.governator.guice;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.inject.AbstractModule;
import com.google.inject.Binding;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.matcher.Matchers;
import com.google.inject.spi.ProvisionListener;
import com.netflix.governator.lifecycle.LifecycleListener;
import com.netflix.governator.lifecycle.LifecycleManager;
import com.netflix.governator.lifecycle.LifecycleMethods;
import static com.netflix.governator.internal.BinaryConstant.*;
class InternalLifecycleModule extends AbstractModule implements ProvisionListener {
private static final Logger LOGGER = LoggerFactory.getLogger(InternalLifecycleModule.class);
private final LoadingCache<Class<?>, LifecycleMethods> lifecycleMethods = CacheBuilder
.newBuilder()
.initialCapacity(I13_8192) // number of classes with metadata
.concurrencyLevel(I8_256) // number of concurrent metadata producers (no locks for read)
.softValues()
.build(new CacheLoader<Class<?>, LifecycleMethods>() {
@Override
public LifecycleMethods load(Class<?> key) throws Exception {
return new LifecycleMethods(key);
}
});
private final AtomicReference<LifecycleManager> lifecycleManager;
InternalLifecycleModule(AtomicReference<LifecycleManager> lifecycleManager) {
this.lifecycleManager = lifecycleManager;
}
@Override
public void configure() {
bindListener(
Matchers.any(),
this);
}
@Override
public <T> void onProvision(ProvisionInvocation<T> provision) {
T instance = provision.provision();
if (instance != null) {
Binding<T> binding = provision.getBinding();
LifecycleManager manager = lifecycleManager.get();
if (manager != null) {
Key<T> bindingKey = binding.getKey();
LOGGER.trace("provisioning instance of {}", bindingKey);
TypeLiteral<T> bindingType = bindingKey.getTypeLiteral();
for (LifecycleListener listener : manager.getListeners()) {
listener.objectInjected(bindingType, instance);
}
try {
LifecycleMethods methods = lifecycleMethods.get(instance.getClass());
if (methods.hasLifecycleAnnotations()) {
manager.add(instance, binding, methods);
}
} catch (ExecutionException e) {
// caching problem
throw new RuntimeException(e);
} catch (Throwable e) {
// unknown problem will abort injector start up
throw new Error(e);
}
}
}
}
}