7b2e267a1442250a3fbfe577519a636beba4e338
[sdc.git] /
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  * Modifications Copyright (c) 2019 Samsung
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 package org.onap.config.impl;
19
20 import java.io.File;
21 import java.sql.Timestamp;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.HashSet;
25 import java.util.LinkedHashMap;
26 import java.util.Map;
27 import java.util.Set;
28 import org.apache.commons.configuration2.CombinedConfiguration;
29 import org.apache.commons.configuration2.CompositeConfiguration;
30 import org.apache.commons.configuration2.Configuration;
31 import org.apache.commons.configuration2.FileBasedConfiguration;
32 import org.apache.commons.configuration2.builder.BasicConfigurationBuilder;
33 import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
34 import org.onap.config.ConfigurationUtils;
35 import org.onap.config.Constants;
36 import org.openecomp.sdc.logging.api.Logger;
37 import org.openecomp.sdc.logging.api.LoggerFactory;
38
39 public final class ConfigurationRepository {
40
41     private static final Logger logger = LoggerFactory.getLogger(ConfigurationRepository.class);
42     private static final ConfigurationRepository REPO = new ConfigurationRepository();
43
44     private final Set<String> tenants = Collections.synchronizedSet(new HashSet<>());
45
46     private final Set<String> namespaces = Collections.synchronizedSet(new HashSet<>());
47
48     private final Map<String, ConfigurationHolder> store = Collections.synchronizedMap(
49
50             new LinkedHashMap<String, ConfigurationHolder>(16, 0.75f, true) {
51
52                 @Override
53                 protected boolean removeEldestEntry(Map.Entry eldest) {
54                     try {
55                         return size() > getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
56                                 .getInt("config.size.max");
57                     } catch (Exception exception) {
58                         logger.info("ConfigurationException", exception);
59                         return false;
60                     }
61                 }
62             });
63
64     private ConfigurationRepository() {
65         tenants.add(Constants.DEFAULT_TENANT);
66         namespaces.add(Constants.DEFAULT_NAMESPACE);
67     }
68
69     public static ConfigurationRepository lookup() {
70         return REPO;
71     }
72
73     public Set<String> getTenants() {
74         return tenants;
75     }
76
77     public Set<String> getNamespaces() {
78         return namespaces;
79     }
80
81     public boolean isValidTenant(String tenant) {
82         return tenant != null && tenants.contains(tenant.toUpperCase());
83     }
84
85     public boolean isValidNamespace(String namespace) {
86         return namespace != null && namespaces.contains(namespace.toUpperCase());
87     }
88
89     public Configuration getConfigurationFor(String tenant, String namespace) throws Exception {
90         String module = tenant + Constants.KEY_ELEMENTS_DELIMITER + namespace;
91         ConfigurationHolder config = store.get(module);
92         return config.getConfiguration();
93     }
94
95     public void populateConfiguration(String key, Configuration builder) {
96         store.put(key, new ConfigurationHolder(builder));
97         populateTenantsNamespace(key);
98     }
99
100     private void populateTenantsNamespace(String key) {
101         String[] array = key.split(Constants.KEY_ELEMENTS_DELIMITER);
102         if (!array[1].equalsIgnoreCase(Constants.DB_NAMESPACE)) {
103             tenants.add(array[0]);
104             namespaces.add(array[1]);
105         }
106     }
107
108     public void populateOverrideConfiguration(String key, File file) {
109
110         ConfigurationHolder holder = store.get(key);
111
112         if (holder == null) {
113             holder = new ConfigurationHolder(new CombinedConfiguration());
114             store.put(key, holder);
115         }
116
117         holder.addOverrideConfiguration(file.getAbsolutePath(), ConfigurationUtils.getConfigurationBuilder(file));
118         populateTenantsNamespace(key);
119     }
120
121     private class ConfigurationHolder {
122
123         private final Map<String, FileBasedConfigurationBuilder<FileBasedConfiguration>> overrideConfiguration =
124                 new LinkedHashMap<>();
125         private BasicConfigurationBuilder<Configuration> builder;
126         private Timestamp lastConfigurationBuildTime;
127         private Configuration config;
128         private Configuration composite;
129
130         ConfigurationHolder(BasicConfigurationBuilder builder) {
131             this.builder = builder;
132         }
133
134         ConfigurationHolder(Configuration builder) {
135             this.config = builder;
136         }
137
138         void addOverrideConfiguration(String path, BasicConfigurationBuilder<FileBasedConfiguration> builder) {
139             overrideConfiguration.put(path.toUpperCase(), (FileBasedConfigurationBuilder) builder);
140             getEffectiveConfiguration(config, overrideConfiguration.values());
141         }
142
143         private Configuration getEffectiveConfiguration(Configuration configuration,
144                                                         Collection<FileBasedConfigurationBuilder<FileBasedConfiguration>> list) {
145             try {
146                 CompositeConfiguration cc = new CompositeConfiguration();
147                 for (FileBasedConfigurationBuilder<FileBasedConfiguration> b : list) {
148                     cc.addConfiguration(b.getConfiguration());
149                 }
150                 cc.addConfiguration(configuration);
151                 composite = cc;
152                 return composite;
153             } catch (Exception exception) {
154                 logger.info("ConfigurationException", exception);
155                 return null;
156             }
157         }
158
159         public Configuration getConfiguration() throws Exception {
160             if (config == null) {
161                 config = builder.getConfiguration();
162                 lastConfigurationBuildTime = new Timestamp(System.currentTimeMillis());
163             } else if (lastConfigurationBuildTime != null
164                     && System.currentTimeMillis() - lastConfigurationBuildTime.getTime()
165                     > getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
166                     .getInt("config.refresh.interval")) {
167                 lastConfigurationBuildTime = new Timestamp(System.currentTimeMillis());
168             }
169
170             if (composite == null && overrideConfiguration.size() != 0) {
171                 composite = getEffectiveConfiguration(config, overrideConfiguration.values());
172             }
173
174             return overrideConfiguration.size() == 0 ? config : composite;
175         }
176     }
177 }