io.micronaut.openapi.visitor.AnnProcessorEnvironment Maven / Gradle / Ivy
/*
* Copyright 2017-2023 original authors
*
* 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
*
* https://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.micronaut.openapi.visitor;
import io.micronaut.context.ApplicationContextConfiguration;
import io.micronaut.context.env.ActiveEnvironment;
import io.micronaut.context.env.CachedEnvironment;
import io.micronaut.context.env.DefaultEnvironment;
import io.micronaut.context.env.Environment;
import io.micronaut.context.env.PropertiesPropertySourceLoader;
import io.micronaut.context.env.PropertySource;
import io.micronaut.context.env.PropertySourceLoader;
import io.micronaut.context.env.yaml.YamlPropertySourceLoader;
import io.micronaut.context.exceptions.ConfigurationException;
import io.micronaut.core.io.ResourceLoader;
import io.micronaut.core.io.file.DefaultFileSystemResourceLoader;
import io.micronaut.core.io.scan.DefaultClassPathResourceLoader;
import io.micronaut.core.order.OrderUtil;
import io.micronaut.core.util.StringUtils;
import io.micronaut.inject.visitor.VisitorContext;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import static io.micronaut.openapi.visitor.ConfigUtils.getProjectPath;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_CONFIG_FILE_LOCATIONS;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_ENVIRONMENT_ENABLED;
import static io.micronaut.openapi.visitor.StringUtil.COMMA;
/**
* Specific environment for annotation processing level. Solve problem with access to resources
* from project classpath.
*
* @since 4.5.0
*/
public class AnnProcessorEnvironment extends DefaultEnvironment {
private final List annotationProcessingConfigLocations;
private String projectResourcesPath;
private String projectDir = StringUtils.EMPTY_STRING;
/**
* Construct a new environment for the given configuration.
*
* @param configuration The configuration
* @param context visitor context
*/
public AnnProcessorEnvironment(ApplicationContextConfiguration configuration, VisitorContext context) {
super(configuration, false);
annotationProcessingConfigLocations = new ArrayList<>();
boolean isEnabled = ContextUtils.get(MICRONAUT_ENVIRONMENT_ENABLED, Boolean.class, false, context);
if (isEnabled) {
Path projectPath = getProjectPath(context);
if (projectPath != null) {
projectDir = "file:" + projectPath.toString().replace("\\\\", StringUtil.SLASH);
projectResourcesPath = projectDir + (projectDir.endsWith(StringUtil.SLASH) ? StringUtils.EMPTY_STRING : StringUtil.SLASH) + "src/main/resources/";
}
String configFileLocations = ContextUtils.getOptions(context).get(MICRONAUT_CONFIG_FILE_LOCATIONS);
if (projectResourcesPath != null && StringUtils.isEmpty(configFileLocations)) {
annotationProcessingConfigLocations.add(projectResourcesPath);
} else if (StringUtils.isNotEmpty(configFileLocations)) {
for (String configFileLocation : configFileLocations.split(COMMA)) {
if (!configFileLocation.startsWith("classpath") && !configFileLocation.startsWith("file") && !configFileLocation.startsWith("project")) {
throw new ConfigurationException("Unsupported config location format: " + configFileLocation);
}
if (configFileLocation.startsWith("project")) {
configFileLocation = configFileLocation.replace("project:", projectDir);
}
annotationProcessingConfigLocations.add(configFileLocation);
}
}
}
}
/**
* @param name The name to read property sources
*/
@Override
protected void readPropertySources(String name) {
refreshablePropertySources.clear();
List propertySources = readPropertySourceList(name);
addDefaultPropertySources(propertySources);
String propertySourcesSystemProperty = CachedEnvironment.getProperty(Environment.PROPERTY_SOURCES_KEY);
if (propertySourcesSystemProperty != null) {
if (propertySourcesSystemProperty.startsWith("project")) {
propertySourcesSystemProperty = propertySourcesSystemProperty.replaceAll("project:", projectDir);
}
propertySources.addAll(readPropertySourceListFromFiles(propertySourcesSystemProperty));
}
String propertySourcesEnv = readPropertySourceListKeyFromEnvironment();
if (propertySourcesEnv != null) {
if (propertySourcesEnv.startsWith("project")) {
propertySourcesEnv = propertySourcesEnv.replace("project:", projectDir);
}
propertySources.addAll(readPropertySourceListFromFiles(propertySourcesEnv));
}
refreshablePropertySources.addAll(propertySources);
readConstPropertySources(name, propertySources);
propertySources.addAll(this.propertySources.values());
OrderUtil.sort(propertySources);
for (PropertySource propertySource : propertySources) {
processPropertySource(propertySource, propertySource.getConvention());
}
}
private void readConstPropertySources(String name, List propertySources) {
var propertySourceNames = new HashSet(getActiveNames().size() + 1);
propertySourceNames.add(name);
for (var activeName : getActiveNames()) {
propertySourceNames.add(name + '-' + activeName);
}
for (var constPropertySource : getConstantPropertySources()) {
if (propertySourceNames.contains(constPropertySource.getName())) {
propertySources.add(constPropertySource);
}
}
}
/**
* @param name The name to resolver property sources
*
* @return The list of property sources
*/
@Override
protected List readPropertySourceList(String name) {
var propertySources = new ArrayList();
for (String configLocation : annotationProcessingConfigLocations) {
ResourceLoader resourceLoader;
if (configLocation.equals("classpath:/")) {
resourceLoader = this;
} else if (configLocation.startsWith("classpath:")) {
if (this.resourceLoader instanceof DefaultClassPathResourceLoader defClassPathResourceLoader) {
resourceLoader = defClassPathResourceLoader.forBase(configLocation, false);
} else {
resourceLoader = forBase(configLocation);
}
} else if (configLocation.startsWith("file:")) {
configLocation = configLocation.substring(5);
Path configLocationPath = Paths.get(configLocation);
if (Files.exists(configLocationPath) && Files.isDirectory(configLocationPath) && Files.isReadable(configLocationPath)) {
resourceLoader = new DefaultFileSystemResourceLoader(configLocationPath);
} else {
continue; // Skip not existing config location
}
} else {
throw new ConfigurationException("Unsupported config location format: " + configLocation);
}
readPropSourceList(name, resourceLoader, propertySources);
}
return propertySources;
}
private void readPropSourceList(String name, ResourceLoader resourceLoader, List propertySources) {
Collection propertySourceLoaders = getPropertySourceLoaders();
if (propertySourceLoaders.isEmpty()) {
var propertySourceLoader = new PropertiesPropertySourceLoader(false);
loadPropSourceFromLoader(name, propertySourceLoader, propertySources, resourceLoader);
} else {
for (PropertySourceLoader propertySourceLoader : propertySourceLoaders) {
loadPropSourceFromLoader(name, propertySourceLoader, propertySources, resourceLoader);
}
}
}
@Override
public Collection getPropertySourceLoaders() {
var loaders = new ArrayList(2);
loaders.add(new YamlPropertySourceLoader(false));
loaders.add(new PropertiesPropertySourceLoader(false));
return loaders;
}
private void loadPropSourceFromLoader(String name, PropertySourceLoader propertySourceLoader, List propertySources, ResourceLoader resourceLoader) {
Optional defaultPropertySource = propertySourceLoader.load(name, resourceLoader);
defaultPropertySource.ifPresent(propertySources::add);
Set activeNames = getActiveNames();
int i = 0;
for (String activeName : activeNames) {
Optional propertySource = propertySourceLoader.loadEnv(name, resourceLoader, ActiveEnvironment.of(activeName, i));
propertySource.ifPresent(propertySources::add);
i++;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy