7f753fd1fd908467252ed78644e3cf2ba232a7b5
[sdc.git] / common / onap-common-configuration-management / onap-configuration-management-core / src / main / java / org / onap / config / impl / CliConfigurationImpl.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onap.config.impl;
18
19 import static org.onap.config.Constants.DB_NAMESPACE;
20 import static org.onap.config.Constants.DEFAULT_NAMESPACE;
21 import static org.onap.config.Constants.DEFAULT_TENANT;
22 import static org.onap.config.Constants.KEY_ELEMENTS_DELIMETER;
23 import static org.onap.config.Constants.LOAD_ORDER_KEY;
24 import static org.onap.config.Constants.MBEAN_NAME;
25 import static org.onap.config.Constants.MODE_KEY;
26 import static org.onap.config.Constants.NAMESPACE_KEY;
27
28 import java.io.File;
29 import java.io.PrintWriter;
30 import java.lang.management.ManagementFactory;
31 import java.lang.reflect.Method;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.HashMap;
37 import java.util.HashSet;
38 import java.util.Iterator;
39 import java.util.Map;
40 import java.util.Set;
41 import javax.management.MBeanServer;
42 import javax.management.MBeanServerDelegate;
43 import javax.management.MBeanServerNotification;
44 import javax.management.Notification;
45 import javax.management.ObjectName;
46 import javax.management.StandardMBean;
47 import org.apache.commons.configuration2.CombinedConfiguration;
48 import org.apache.commons.configuration2.CompositeConfiguration;
49 import org.apache.commons.configuration2.Configuration;
50 import org.apache.commons.configuration2.FileBasedConfiguration;
51 import org.apache.commons.configuration2.PropertiesConfiguration;
52 import org.onap.config.ConfigurationUtils;
53 import org.onap.config.Constants;
54 import org.onap.config.api.ConfigurationManager;
55 import org.onap.config.api.Hint;
56 import org.onap.config.type.ConfigurationQuery;
57 import org.onap.config.type.ConfigurationUpdate;
58
59 public final class CliConfigurationImpl extends ConfigurationImpl implements ConfigurationManager {
60
61     public CliConfigurationImpl() throws Exception {
62         MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
63         ObjectName name = new ObjectName(MBEAN_NAME);
64         if (mbs.isRegistered(name)) {
65             mbs.unregisterMBean(name);
66         }
67         mbs.registerMBean(new StandardMBean(this, ConfigurationManager.class), name);
68         mbs.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME,
69                 (notification, handback) -> handleNotification(notification), null, null);
70     }
71
72     public void handleNotification(Notification notification) {
73         if (notification instanceof MBeanServerNotification) {
74             MBeanServerNotification mbs = (MBeanServerNotification) notification;
75             if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(mbs.getType())) {
76                 try {
77                     String mbean = ConfigurationRepository.lookup().getConfigurationFor(DEFAULT_TENANT, DB_NAMESPACE)
78                                            .getString("shutdown.mbean");
79                     if (mbs.getMBeanName().equals(mbean == null ? new ObjectName(MBEAN_NAME) : new ObjectName(mbean))) {
80                         changeNotifier.shutdown();
81                     }
82                 } catch (Exception exception) {
83                     //do nothing.
84                 }
85             } else if (MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(mbs.getType())) {
86                 mbs.getMBeanName();
87             }
88         }
89     }
90
91     public String getConfigurationValue(Map<String, Object> input) {
92         return getConfigurationValue((ConfigurationQuery) getInput(input));
93     }
94
95     private String getConfigurationValue(ConfigurationQuery queryData) {
96         try {
97             if (queryData.isFallback()) {
98                 return ConfigurationUtils.getCommaSeparatedList(
99                         get(queryData.getTenant(), queryData.getNamespace(), queryData.getKey(), String[].class,
100                                 queryData.isLatest() ? Hint.LATEST_LOOKUP : Hint.DEFAULT,
101                                 queryData.isExternalLookup() ? Hint.EXTERNAL_LOOKUP : Hint.DEFAULT,
102                                 queryData.isNodeSpecific() ? Hint.NODE_SPECIFIC : Hint.DEFAULT));
103             } else {
104                 String[] list =
105                         getInternal(queryData.getTenant(), queryData.getNamespace(), queryData.getKey(), String[].class,
106                                 queryData.isLatest() ? Hint.LATEST_LOOKUP : Hint.DEFAULT,
107                                 queryData.isExternalLookup() ? Hint.EXTERNAL_LOOKUP : Hint.DEFAULT,
108                                 queryData.isNodeSpecific() ? Hint.NODE_SPECIFIC : Hint.DEFAULT);
109                 return ConfigurationUtils
110                                .getCommaSeparatedList(list == null ? Collections.emptyList() : Arrays.asList(list));
111             }
112         } catch (Exception exception) {
113             exception.printStackTrace();
114         }
115         return null;
116     }
117
118     private Object getInput(Map<String, Object> input) {
119         Object toReturn = null;
120         try {
121             toReturn = Class.forName(input.get("ImplClass").toString()).newInstance();
122             Method[] methods = toReturn.getClass().getMethods();
123             for (Method method : methods) {
124                 if (input.containsKey(method.getName())) {
125                     method.invoke(toReturn, input.get(method.getName()));
126                 }
127             }
128         } catch (Exception exception) {
129             exception.printStackTrace();
130         }
131
132         return toReturn;
133     }
134
135     public void updateConfigurationValue(Map<String, Object> input) {
136         updateConfigurationValue((ConfigurationUpdate) getInput(input));
137     }
138
139     private void updateConfigurationValue(ConfigurationUpdate updateData) {
140
141         try {
142             if (!ConfigurationRepository.lookup().isValidTenant(updateData.getTenant())) {
143                 throw new RuntimeException("Invalid tenantId.");
144             }
145             if (!ConfigurationRepository.lookup().isValidNamespace(updateData.getNamespace())) {
146                 throw new RuntimeException("Invalid Namespace.");
147             }
148         } catch (NullPointerException e1) {
149             e1.printStackTrace();
150         }
151
152         try {
153             boolean keyPresent = isKeyExists(updateData.getTenant(), updateData.getNamespace(), updateData.getKey());
154             if (keyPresent) {
155                 boolean isUpdated = false;
156                 Object[] paramArray =
157                         new Object[] {updateData.getTenant() + KEY_ELEMENTS_DELIMETER + updateData.getNamespace(),
158                                 System.currentTimeMillis(), updateData.getKey(), getConfigurationValue(updateData),
159                                 updateData.getValue()};
160                 Configuration config = ConfigurationRepository.lookup()
161                                                .getConfigurationFor(updateData.getTenant(), updateData.getNamespace());
162                 if (config instanceof AgglomerateConfiguration || config instanceof CombinedConfiguration) {
163                     CompositeConfiguration cc = new CompositeConfiguration();
164                     cc.addConfiguration(config);
165                     config = cc;
166                 }
167                 CompositeConfiguration configuration = (CompositeConfiguration) config;
168                 int overrideIndex = -1;
169                 for (int i = 0; i < configuration.getNumberOfConfigurations(); i++) {
170                     if (!updateData.isNodeOverride() && (
171                             configuration.getConfiguration(i) instanceof AgglomerateConfiguration
172                                     || configuration.getConfiguration(i) instanceof CombinedConfiguration)) {
173                         configuration.getConfiguration(i).setProperty(updateData.getKey(), updateData.getValue());
174                         isUpdated = true;
175                         break;
176                     } else if (updateData.isNodeOverride() && configuration.getConfiguration(
177                             i) instanceof FileBasedConfiguration) {
178                         configuration.getConfiguration(i).setProperty(updateData.getKey(), updateData.getValue());
179                         isUpdated = true;
180                         overrideIndex = i;
181                         break;
182                     }
183                 }
184                 if (!isUpdated) {
185                     if (updateData.isNodeOverride()) {
186                         PropertiesConfiguration pc = new PropertiesConfiguration();
187                         pc.setProperty(NAMESPACE_KEY,
188                                 updateData.getTenant() + Constants.TENANT_NAMESPACE_SEPARATOR
189                                         + updateData.getNamespace());
190                         pc.setProperty(MODE_KEY, "OVERRIDE");
191                         pc.setProperty(updateData.getKey(), updateData.getValue());
192                         String nodeConfigLocation = System.getProperty("node.config.location");
193                         if (nodeConfigLocation != null && nodeConfigLocation.trim().length() > 0) {
194                             File file = new File(nodeConfigLocation,
195                                     updateData.getTenant() + File.separator + updateData.getNamespace() + File.separator
196                                             + "config.properties");
197                             file.getParentFile().mkdirs();
198                             PrintWriter out = new PrintWriter(file);
199                             pc.write(out);
200                             out.close();
201                             ConfigurationRepository.lookup().populateOverrideConfiguration(
202                                     updateData.getTenant() + KEY_ELEMENTS_DELIMETER + updateData.getNamespace(), file);
203                         }
204                     } else {
205                         configuration.getConfiguration(0).setProperty(updateData.getKey(), updateData.getValue());
206                     }
207                 }
208                 if (updateData.isNodeOverride()) {
209                     ConfigurationRepository.lookup().refreshOverrideConfigurationFor(
210                             updateData.getTenant() + KEY_ELEMENTS_DELIMETER + updateData.getNamespace(), overrideIndex);
211                 }
212             }
213         } catch (Exception exception) {
214             exception.printStackTrace();
215         }
216     }
217
218     private boolean isKeyExists(String tenant, String namespace, String key) {
219         boolean keyExist = false;
220         try {
221             keyExist = ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace).containsKey(key);
222             if (!keyExist && !DEFAULT_TENANT.equals(tenant)) {
223                 keyExist = ConfigurationRepository.lookup().getConfigurationFor(DEFAULT_TENANT, namespace)
224                                    .containsKey(key);
225             }
226             if (!keyExist && !DEFAULT_NAMESPACE.equals(namespace)) {
227                 keyExist = ConfigurationRepository.lookup().getConfigurationFor(tenant, DEFAULT_NAMESPACE)
228                                    .containsKey(key);
229             }
230             if (!keyExist && !DEFAULT_TENANT.equals(tenant) && !DEFAULT_NAMESPACE.equals(namespace)) {
231                 keyExist = ConfigurationRepository.lookup().getConfigurationFor(DEFAULT_TENANT, DEFAULT_NAMESPACE)
232                                    .containsKey(key);
233             }
234         } catch (Exception exception) {
235             exception.printStackTrace();
236         }
237         return keyExist;
238     }
239
240     public Map<String, String> listConfiguration(Map<String, Object> input) {
241         return listConfiguration((ConfigurationQuery) getInput(input));
242     }
243
244     private Map<String, String> listConfiguration(ConfigurationQuery query) {
245         Map<String, String> map = new HashMap<>();
246         try {
247             Collection<String> keys = getKeys(query.getTenant(), query.getNamespace());
248             for (String key : keys) {
249                 map.put(key, getConfigurationValue(query.key(key)));
250             }
251         } catch (Exception exception) {
252             exception.printStackTrace();
253             return null;
254         }
255         return map;
256     }
257
258     private ArrayList<String> getInMemoryKeys(String tenant, String namespace) {
259         ArrayList<String> keys = new ArrayList<>();
260
261         try {
262             Iterator<String> iter = ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace).getKeys();
263             while (iter.hasNext()) {
264                 String key = iter.next();
265                 if (!(key.equals(NAMESPACE_KEY) || key.equals(MODE_KEY) || key.equals(LOAD_ORDER_KEY))) {
266                     keys.add(key);
267                 }
268             }
269         } catch (Exception exception) {
270             //do nothing
271         }
272
273         return keys;
274     }
275
276     @Override
277     public boolean updateConfigurationValues(String tenant, String namespace, Map configKeyValueStore) {
278         boolean valueToReturn = true;
279         for (String s : (Iterable<String>) configKeyValueStore.keySet()) {
280             try {
281                 String key = s;
282                 ConfigurationUpdate updateData = new ConfigurationUpdate();
283                 updateData.tenant(tenant).namespace(namespace).key(key);
284                 updateData.value(configKeyValueStore.get(key).toString());
285                 updateConfigurationValue(updateData);
286             } catch (Exception exception) {
287                 exception.printStackTrace();
288                 valueToReturn = false;
289             }
290         }
291         return valueToReturn;
292     }
293
294     @Override
295     public Collection<String> getTenants() {
296         return ConfigurationRepository.lookup().getTenants();
297     }
298
299     @Override
300     public Collection<String> getNamespaces() {
301         return ConfigurationRepository.lookup().getNamespaces();
302     }
303
304     @Override
305     public Collection<String> getKeys(String tenant, String namespace) {
306         Set<String> keyCollection = new HashSet<>();
307         keyCollection.addAll(getInMemoryKeys(tenant, DEFAULT_NAMESPACE));
308         keyCollection.addAll(getInMemoryKeys(tenant, namespace));
309         keyCollection.addAll(getInMemoryKeys(DEFAULT_TENANT, namespace));
310         keyCollection.addAll(getInMemoryKeys(DEFAULT_TENANT, DEFAULT_NAMESPACE));
311         return keyCollection;
312     }
313 }