PageRenderTime 228ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/webapp/src/main/java/no/bekk/bekkopen/cde/jetty/config/SystemPropertiesLoader.java

https://github.com/bekkopen/Continuous-Delivery-example
Java | 295 lines | 249 code | 46 blank | 0 comment | 38 complexity | 69f78fbe55648b2b075c9c5dc10562b8 MD5 | raw file
  1. package no.bekk.bekkopen.cde.jetty.config;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.net.InetAddress;
  6. import java.net.UnknownHostException;
  7. import java.util.Enumeration;
  8. import java.util.HashMap;
  9. import java.util.Map;
  10. import java.util.Properties;
  11. import java.util.Set;
  12. import java.util.TreeSet;
  13. import javax.naming.ConfigurationException;
  14. import org.apache.commons.lang.StringUtils;
  15. import org.slf4j.Logger;
  16. import org.slf4j.LoggerFactory;
  17. import com.google.common.collect.Sets;
  18. public final class SystemPropertiesLoader {
  19. static final String ENVIRONMENT_GROUP_KEY = "environmentGroup";
  20. private static final String DOT = "\\.";
  21. static final Set<String> ENVIRONMENTS = Sets.newHashSet("node1", "node2", "node3");
  22. private static String environment;
  23. static final Set<String> PROD_ENVIRONMENTS = Sets.newHashSet("node1", "node2", "node3");
  24. private static String environmentGroup;
  25. static final Set<String> ENVIRONMENT_GROUPS = Sets.newHashSet("prod", "unknown");
  26. static final String PROD_GROUP = "prod";
  27. static final Object UNKNOWN_GROUP = "unknown";
  28. private static final String CONFIG = "config";
  29. private static final String SECRETS = "secrets";
  30. static final String WEBAPP = "webapp";
  31. static final Set<String> ARTIFACTS = Sets.newHashSet(WEBAPP);
  32. private static EnvironmentResolver environmentResolver = new EnvironmentResolver();
  33. private SystemPropertiesLoader() {
  34. }
  35. public static void loadWebConfig() throws IOException, ConfigurationException {
  36. loadConfig(WEBAPP);
  37. }
  38. @SuppressWarnings({ "unchecked", "rawtypes" })
  39. public static void loadSecrets() throws IOException, ConfigurationException {
  40. File configFile = new File(getConfigPath(SECRETS));
  41. if (configFile.exists()) {
  42. Properties properties = loadProperties(configFile);
  43. environment = environmentResolver.getEnvironment();
  44. if (ENVIRONMENTS.contains(environment)) {
  45. String propertyHostName = properties.getProperty("hostname");
  46. if (!environment.equals(propertyHostName)) {
  47. String message = "System property hostname does not match the real hostname. " + "Property file says "
  48. + propertyHostName + ", but the real hostname is " + environment + ".";
  49. throw new ConfigurationException(message);
  50. }
  51. }
  52. setSecretProperties(properties);
  53. getLogger().info("Secret properties loaded from {}: {}", configFile.getAbsolutePath(),
  54. propsToString(new HashMap(properties), true));
  55. } else {
  56. throw new ConfigurationException("File not found: " + configFile.getAbsolutePath());
  57. }
  58. }
  59. private static void loadConfig(final String artifact) throws IOException, ConfigurationException {
  60. if (!ARTIFACTS.contains(artifact)) {
  61. throw new ConfigurationException("Artifact must be one of " + ARTIFACTS.toString() + ", but was " + artifact);
  62. }
  63. File configFile = new File(getConfigPath(CONFIG));
  64. if (configFile.isDirectory()) {
  65. configFile = new File(configFile, artifact + ".properties");
  66. }
  67. if (configFile.exists()) {
  68. Map<String, String> systemPropertiesMap = getConfigProperties(configFile, artifact, environmentResolver.getEnvironment());
  69. setSystemProperties(systemPropertiesMap);
  70. getLogger().info("System properties loaded from {}: {}", configFile.getAbsolutePath(),
  71. propsToString(systemPropertiesMap, false));
  72. } else {
  73. throw new ConfigurationException("File not found: " + configFile.getAbsolutePath());
  74. }
  75. }
  76. private static String propsToString(final Map<String, String> systemPropertiesMap, final boolean secret) {
  77. StringBuilder propsString = new StringBuilder();
  78. TreeSet<String> keys = new TreeSet<String>(systemPropertiesMap.keySet());
  79. for (String key : keys) {
  80. String value = systemPropertiesMap.get(key);
  81. propsString.append("\n");
  82. propsString.append(key);
  83. propsString.append("=");
  84. if (secret) {
  85. propsString.append("******");
  86. } else {
  87. propsString.append(value);
  88. }
  89. }
  90. return propsString.toString();
  91. }
  92. static Map<String, String> getConfigProperties(final File configFile, final String artifact, final String environment)
  93. throws IOException, ConfigurationException {
  94. Properties properties = loadProperties(configFile);
  95. checkFormat(properties);
  96. Map<String, String> environmentPropertiesPri1 = new HashMap<String, String>();
  97. Map<String, String> environmentPropertiesPri2 = new HashMap<String, String>();
  98. Map<String, String> environmentGroupPropertiesPri3 = new HashMap<String, String>();
  99. Map<String, String> environmentGroupPropertiesPri4 = new HashMap<String, String>();
  100. Map<String, String> artifactPropertiesPri5 = new HashMap<String, String>();
  101. Map<String, String> defaultPropertiesPri6 = new HashMap<String, String>();
  102. environmentGroup = findEnviromentGroup(environment);
  103. System.setProperty(ENVIRONMENT_GROUP_KEY, environmentGroup);
  104. Enumeration<Object> propEnum = properties.keys();
  105. while (propEnum.hasMoreElements()) {
  106. String property = (String) propEnum.nextElement();
  107. String originalProperty = property;
  108. if (propertyForOtherEnvironment(property, environment, environmentGroup)) {
  109. continue;
  110. }
  111. if (property.matches(environment + DOT + artifact + "\\..*")) {
  112. property = property.replaceFirst(environment + DOT + artifact + DOT, "");
  113. environmentPropertiesPri1.put(property, properties.getProperty(originalProperty));
  114. continue;
  115. }
  116. if (property.matches(environment + "\\..*")) {
  117. property = property.replaceFirst(environment + DOT, "");
  118. if (!isArtifactProperty(property)) {
  119. environmentPropertiesPri2.put(property, properties.getProperty(originalProperty));
  120. }
  121. continue;
  122. }
  123. if (property.matches(environmentGroup + DOT + artifact + "\\..*")) {
  124. property = property.replaceFirst(environmentGroup + DOT + artifact + DOT, "");
  125. environmentGroupPropertiesPri3.put(property, properties.getProperty(originalProperty));
  126. continue;
  127. }
  128. if (property.matches(environmentGroup + "\\..*")) {
  129. property = property.replaceFirst(environmentGroup + DOT, "");
  130. if (!isArtifactProperty(property)) {
  131. environmentGroupPropertiesPri4.put(property, properties.getProperty(originalProperty));
  132. }
  133. continue;
  134. }
  135. if (property.matches(artifact + "\\..*")) {
  136. property = property.replaceFirst(artifact + DOT, "");
  137. artifactPropertiesPri5.put(property, properties.getProperty(originalProperty));
  138. continue;
  139. }
  140. if (!isArtifactProperty(property)) {
  141. defaultPropertiesPri6.put(property, properties.getProperty(originalProperty));
  142. }
  143. }
  144. Map<String, String> systemPropertiesMap = new HashMap<String, String>();
  145. systemPropertiesMap.putAll(defaultPropertiesPri6);
  146. systemPropertiesMap.putAll(artifactPropertiesPri5);
  147. systemPropertiesMap.putAll(environmentGroupPropertiesPri4);
  148. systemPropertiesMap.putAll(environmentGroupPropertiesPri3);
  149. systemPropertiesMap.putAll(environmentPropertiesPri2);
  150. systemPropertiesMap.putAll(environmentPropertiesPri1);
  151. return systemPropertiesMap;
  152. }
  153. private static String getConfigPath(final String property) throws ConfigurationException {
  154. final String path = System.getProperty(property);
  155. if (path == null) {
  156. throw new ConfigurationException("System property \"" + property + "\" undefined.");
  157. }
  158. return path;
  159. }
  160. static Properties loadProperties(final File configFile) throws IOException {
  161. FileInputStream configStream = new FileInputStream(configFile);
  162. Properties properties = new Properties();
  163. try {
  164. properties.load(configStream);
  165. } finally {
  166. configStream.close();
  167. }
  168. return properties;
  169. }
  170. private static void checkFormat(final Properties properties) throws ConfigurationException {
  171. Map<String, String> errors = new HashMap<String, String>();
  172. Enumeration<Object> propEnum = properties.keys();
  173. while (propEnum.hasMoreElements()) {
  174. String property = (String) propEnum.nextElement();
  175. String artefaktOrRegex = StringUtils.join(ARTIFACTS, '|');
  176. if (property.matches(".*(" + artefaktOrRegex + ")\\..*(" + artefaktOrRegex + ").*")) {
  177. errors.put(property, "artefakt (" + StringUtils.join(ARTIFACTS, ',')
  178. + ") can only be specified once per property and never together!");
  179. }
  180. for (String environmentGroup : ENVIRONMENT_GROUPS) {
  181. if (property.matches(".*\\." + environmentGroup + ".*")) {
  182. errors
  183. .put(property, "environment group (" + StringUtils.join(ENVIRONMENT_GROUPS, ',')
  184. + ") is only allowed as prefix!");
  185. }
  186. }
  187. for (String miljo : ENVIRONMENTS) {
  188. if (property.matches(".*\\." + miljo + ".*")) {
  189. errors.put(property, "environment (" + StringUtils.join(ENVIRONMENTS, ',') + ") is only allowed as prefix!");
  190. }
  191. }
  192. }
  193. if (!errors.isEmpty()) {
  194. throw new ConfigurationException(errors.size() + " error in properties: " + propsToString(errors, false));
  195. }
  196. }
  197. private static void setSystemProperties(final Map<String, String> systemPropertiesMap) {
  198. for (String key : systemPropertiesMap.keySet()) {
  199. System.setProperty(key, systemPropertiesMap.get(key));
  200. }
  201. }
  202. private static String findEnviromentGroup(final String miljo) {
  203. if (PROD_ENVIRONMENTS.contains(miljo)) {
  204. return PROD_GROUP;
  205. }
  206. return "unknown";
  207. }
  208. private static boolean propertyForOtherEnvironment(final String property, final String environment, final String environmentGroup) {
  209. String[] propertySplit = property.split(DOT);
  210. if (ENVIRONMENTS.contains(propertySplit[0]) && !propertySplit[0].equals(environment)) {
  211. return true;
  212. }
  213. if (ENVIRONMENT_GROUPS.contains(propertySplit[0]) && !propertySplit[0].equals(environmentGroup)) {
  214. return true;
  215. }
  216. return false;
  217. }
  218. static boolean isArtifactProperty(final String property) {
  219. String artifacts = StringUtils.join(ARTIFACTS, '|');
  220. String artifactMiddle = ".*\\.(" + artifacts + ")\\..*";
  221. String artifactStart = "^(" + artifacts + ")\\..*";
  222. if (property.matches("(" + artifactStart + "|" + artifactMiddle + ")")) {
  223. return true;
  224. }
  225. return false;
  226. }
  227. private static void setSecretProperties(final Properties properties) {
  228. Enumeration<Object> propEnum = properties.keys();
  229. while (propEnum.hasMoreElements()) {
  230. String property = (String) propEnum.nextElement();
  231. System.setProperty(property, properties.getProperty(property));
  232. }
  233. }
  234. static void setEnvironmentResolver(final EnvironmentResolver environmentResolver) {
  235. SystemPropertiesLoader.environmentResolver = environmentResolver;
  236. }
  237. static class EnvironmentResolver {
  238. String getEnvironment() throws UnknownHostException, ConfigurationException {
  239. String environment = hostname();
  240. return environment;
  241. }
  242. String hostname() throws UnknownHostException {
  243. return InetAddress.getLocalHost().getHostName();
  244. }
  245. }
  246. private static Logger getLogger() {
  247. return LoggerFactory.getLogger(SystemPropertiesLoader.class);
  248. }
  249. }