/*
* Copyright 2010 Proofpoint, 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 io.airlift.configuration;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.inject.Binding;
import com.google.inject.ConfigurationException;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.spi.DefaultElementVisitor;
import com.google.inject.spi.Element;
import com.google.inject.spi.InstanceBinding;
import com.google.inject.spi.Message;
import com.google.inject.spi.ProviderInstanceBinding;
import java.util.Collection;
import java.util.List;
import static java.util.Collections.singletonList;
public final class Configuration
{
private Configuration()
{
}
public static List<Message> processConfiguration(ConfigurationFactory configurationFactory, WarningsMonitor warningsMonitor, Module... modules)
{
return processConfiguration(configurationFactory, warningsMonitor, ImmutableList.copyOf(modules));
}
public static List<Message> processConfiguration(ConfigurationFactory configurationFactory, WarningsMonitor warningsMonitor, Collection<? extends Module> modules)
{
// some modules need access to configuration factory so they can lazy register additional config classes
// initialize configuration factory
modules.stream()
.filter(ConfigurationAwareModule.class::isInstance)
.map(ConfigurationAwareModule.class::cast)
.forEach(module -> module.setConfigurationFactory(configurationFactory));
List<Message> messages = Lists.newArrayList();
ElementsIterator elementsIterator = new ElementsIterator(modules);
for (Element element : elementsIterator) {
element.acceptVisitor(new DefaultElementVisitor<Void>()
{
@Override
public <T> Void visit(Binding<T> binding)
{
// look for default configs
if (binding instanceof InstanceBinding) {
InstanceBinding<T> instanceBinding = (InstanceBinding<T>) binding;
if (instanceBinding.getInstance() instanceof ConfigDefaultsHolder) {
configurationFactory.registerConfigDefaults((ConfigDefaultsHolder<?>) instanceBinding.getInstance());
}
}
return null;
}
});
}
for (Element element : elementsIterator) {
element.acceptVisitor(new DefaultElementVisitor<Void>()
{
@Override
public <T> Void visit(Binding<T> binding)
{
// look for ConfigurationProviders...
if (binding instanceof ProviderInstanceBinding) {
ProviderInstanceBinding<?> providerInstanceBinding = (ProviderInstanceBinding<?>) binding;
Provider<?> provider = providerInstanceBinding.getProviderInstance();
if (provider instanceof ConfigurationAwareProvider) {
ConfigurationAwareProvider<?> configurationProvider = (ConfigurationAwareProvider<?>) provider;
// give the provider the configuration factory
configurationProvider.setConfigurationFactory(configurationFactory);
configurationProvider.setWarningsMonitor(warningsMonitor);
try {
// call the getter which will cause object creation
configurationProvider.get();
}
catch (ConfigurationException e) {
// if we got errors, add them to the errors list
for (Message message : e.getErrorMessages()) {
messages.add(new Message(singletonList(binding.getSource()), message.getMessage(), message.getCause()));
}
}
}
}
return null;
}
});
}
return messages;
}
}