All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openl.spring.env.ApplicationPropertySource Maven / Gradle / Ivy

The newest version!
package org.openl.spring.env;

import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.PropertyResolver;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import org.openl.util.CollectionUtils;
import org.openl.util.PropertiesUtils;
import org.openl.util.StringUtils;

/**
 * Application properties can be get as combinations of locations and names. If a location is a folder then it is
 * concatenated with each name. For example:
 * 

* application name (from the Spring application context): OpenL Studio
* Spring active profiles: prod, qa
* locations: file:, file:openl.properties, file:openl/
* names: application.properties, {appName}.properties, {profile}.properties
*
* Then the list of resources to search is (next resource overides previous): *

    *
  1. file:application.properties
  2. *
  3. file:WebStudio.properties
  4. *
  5. file:prod.properties
  6. *
  7. file:qa.properties
  8. *
  9. file:openl.properties
  10. *
  11. file:openl/application.properties
  12. *
  13. file:openl/WebStudio.properties
  14. *
  15. file:openl/prod.properties
  16. *
  17. file:openl/qa.properties
  18. *
*

* Default Application externalized configuration:
* Can be overridden using {@code openl.config.name} or {@code spring.config.name} properties for names.
* And {@code openl.config.location} or {@code spring.config.location} properties for folders and locations. *

    *
  1. classpath:application*-default.properties
  2. *
  3. classpath:application.properties
  4. *
  5. classpath:{appName}.properties
  6. *
  7. classpath:config/application.properties
  8. *
  9. classpath:config/{appName}.properties
  10. *
  11. file:application.properties
  12. *
  13. file:{appName}.properties
  14. *
  15. file:conf/application.properties
  16. *
  17. file:conf/{appName}.properties
  18. *
  19. file:config/application.properties
  20. *
  21. file:config/{appName}.properties
  22. *
  23. file:${user.home}/application.properties
  24. *
  25. file:${user.home}/{appName}.properties
  26. *
  27. classpath:application-{profile}.properties
  28. *
  29. classpath:{appName}-{profile}.properties
  30. *
  31. classpath:config/application-{profile}.properties
  32. *
  33. classpath:config/{appName}-{profile}.properties
  34. *
  35. file:application-{profile}.properties
  36. *
  37. file:{appName}-{profile}.properties
  38. *
  39. file:conf/application-{profile}.properties
  40. *
  41. file:config/application-{profile}.properties
  42. *
  43. file:conf/{appName}-{profile}.properties
  44. *
  45. file:config/{appName}-{profile}.properties
  46. *
  47. file:${user.home}/application-{profile}.properties
  48. *
  49. file:${user.home}/{appName}-{profile}.properties
  50. *
* * @author Yury Molchan * @see Spring * Boot. Externalized Configuration. */ public class ApplicationPropertySource extends EnumerablePropertySource>> { private static final Logger LOG = LoggerFactory.getLogger(ApplicationPropertySource.class); public static final String PROPS_NAME = "OpenL application properties"; private static final String APP_NAME_TAG = "{appName}"; private static final String PROFILE_TAG = "{profile}"; private final String appName; private final String[] profiles; private final PropertyResolver resolver; private final Map source = new HashMap<>(); private final Map profiledSource = new HashMap<>(); ApplicationPropertySource(PropertyResolver resolver, String appName, String... profiles) { super(PROPS_NAME, new LinkedList<>()); this.resolver = resolver; this.appName = appName; this.profiles = profiles; addLocations(); } private static Object getInfo(Resource resource) { try { return resource.getURL(); } catch (Exception e) { LOG.debug("Ignored error: ", e); return resource; } } private void addLocations() { String[] lc = resolvePlaceholders("${openl.config.location}"); String[] nm = resolvePlaceholders("${openl.config.name}"); for (String location : lc) { if (location.endsWith("/") || location.endsWith("\\") || location.endsWith(":")) { // Folder, schema root, Windows disk. for (String name : nm) { addLocation(location + name); } } else { // direct location addLocation(location); } } } private String[] resolvePlaceholders(String value) { String resolved = resolver.resolvePlaceholders(value); if (StringUtils.isBlank(resolved)) { ConfigLog.LOG.debug("! Empty: '{}'", value); return StringUtils.EMPTY_STRING_ARRAY; } return StringUtils.split(resolved, ','); } /** * The next source should override the previous. */ private void addLocation(String location) { if (location.contains(APP_NAME_TAG)) { if (StringUtils.isBlank(appName)) { ConfigLog.LOG.debug("- No app name: '{}'", location); } else { location = location.replace(APP_NAME_TAG, appName); } } if (location.contains(PROFILE_TAG)) { if (CollectionUtils.isEmpty(profiles)) { ConfigLog.LOG.debug("- No profiles: '{}'", location); } else { for (String profile : profiles) { addLocation(location.replace(PROFILE_TAG, profile), true); } } } else { addLocation(location, false); } } private void addLocation(String location, boolean isProfiled) { Resource[] resources; try { resources = new PathMatchingResourcePatternResolver().getResources(location); } catch (IOException e) { ConfigLog.LOG.debug("! Error: '{}'", location, e); return; } if (CollectionUtils.isEmpty(resources)) { ConfigLog.LOG.debug("- Not found: [{}]", location); return; } Arrays.sort(resources, Comparator.comparing(Resource::getFilename, Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder()))); for (Resource resource : resources) { try { if (resource.exists()) { Map props = new HashMap<>(); try (var in = resource.getInputStream()) { PropertiesUtils.load(in, props::put); } if (isProfiled) { profiledSource.putAll(props); } else { source.putAll(props); } ConfigLog.LOG.info("+ Load: [{}] '{}' ({} properties)", location, getInfo(resource), props.size()); } else { ConfigLog.LOG.debug("- Not exist: [{}] '{}'", location, getInfo(resource)); } } catch (Exception ex) { ConfigLog.LOG.debug("! Error: [{}] '{}'", location, getInfo(resource), ex); } } } @Override public Object getProperty(String name) { Object propertyInternal = getPropertyInternal(name); if (propertyInternal != null) { String value = propertyInternal.toString(); value = StringUtils.trimToEmpty(value); return DynamicPropertySource.decode(value); } return propertyInternal; } private Object getPropertyInternal(String name) { Object candidate = profiledSource.get(name); if (candidate != null) { return candidate; } return source.get(name); } @Override public boolean containsProperty(String name) { return profiledSource.containsKey(name) || source.containsKey(name); } @Override public String[] getPropertyNames() { Set names = new TreeSet<>(); names.addAll(profiledSource.keySet()); names.addAll(source.keySet()); return names.toArray(StringUtils.EMPTY_STRING_ARRAY); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy