blob: c3252bc31e2edf16c5c5a31c03c38e0cab7fd7c5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.geronimo.config.cdi;
import org.apache.geronimo.config.DefaultConfigProvider;
import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeShutdown;
import javax.enterprise.inject.spi.DeploymentException;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.ProcessInjectionPoint;
import javax.inject.Provider;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
*/
public class ConfigExtension implements Extension {
private Config config;
private static final Predicate<InjectionPoint> NOT_PROVIDERS = ip -> (ip.getType() instanceof Class) || (ip.getType() instanceof ParameterizedType && ((ParameterizedType)ip.getType()).getRawType() != Provider.class);
private static final Map<Type, Type> REPLACED_TYPES = new HashMap<>();
static {
REPLACED_TYPES.put(double.class, Double.class);
REPLACED_TYPES.put(int.class, Integer.class);
REPLACED_TYPES.put(float.class, Float.class);
REPLACED_TYPES.put(long.class, Long.class);
REPLACED_TYPES.put(boolean.class, Boolean.class);
}
private Set<InjectionPoint> injectionPoints = new HashSet<>();
public void collectConfigProducer(@Observes ProcessInjectionPoint<?, ?> pip) {
ConfigProperty configProperty = pip.getInjectionPoint().getAnnotated().getAnnotation(ConfigProperty.class);
if (configProperty != null) {
injectionPoints.add(pip.getInjectionPoint());
}
}
public void registerConfigProducer(@Observes AfterBeanDiscovery abd, BeanManager bm) {
Set<Type> types = injectionPoints.stream()
.filter(NOT_PROVIDERS)
.map(ip -> REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType()))
.collect(Collectors.toSet());
Set<Type> providerTypes = injectionPoints.stream()
.filter(NOT_PROVIDERS.negate())
.map(ip -> ((ParameterizedType)ip.getType()).getActualTypeArguments()[0])
.collect(Collectors.toSet());
types.addAll(providerTypes);
types.stream()
.map(type -> new ConfigInjectionBean(bm, type))
.forEach(abd::addBean);
}
public void validate(@Observes AfterDeploymentValidation add) {
List<String> deploymentProblems = new ArrayList<>();
config = ConfigProvider.getConfig();
for (InjectionPoint injectionPoint : injectionPoints) {
Type type = injectionPoint.getType();
// replace native types with their Wrapper types
type = REPLACED_TYPES.getOrDefault(type, type);
ConfigProperty configProperty = injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class);
if (type instanceof Class) {
// a direct injection of a ConfigProperty
// that means a Converter must exist.
String key = ConfigInjectionBean.getConfigKey(injectionPoint, configProperty);
if ((isDefaultUnset(configProperty.defaultValue()))
&& !config.getOptionalValue(key, (Class) type).isPresent()) {
deploymentProblems.add("No Config Value exists for " + key);
}
}
}
if (!deploymentProblems.isEmpty()) {
add.addDeploymentProblem(new DeploymentException("Error while validating Configuration\n"
+ String.join("\n", deploymentProblems)));
}
}
public void shutdown(@Observes BeforeShutdown bsd) {
DefaultConfigProvider.instance().releaseConfig(config);
}
static boolean isDefaultUnset(String defaultValue) {
return defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);
}
}