Merge "fix connection state machine"
[ccsdk/features.git] / sdnr / wt / common / src / main / java / org / onap / ccsdk / features / sdnr / wt / common / configuration / ConfigurationFileRepresentation.java
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP : ccsdk features
4  * ================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property.
6  * All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  *
21  */
22 package org.onap.ccsdk.features.sdnr.wt.common.configuration;
23
24 import java.io.BufferedReader;
25 import java.io.BufferedWriter;
26 import java.io.File;
27 import java.io.FileReader;
28 import java.io.FileWriter;
29 import java.io.IOException;
30 import java.util.HashMap;
31 import java.util.Optional;
32
33 import org.onap.ccsdk.features.sdnr.wt.common.configuration.filechange.ConfigFileObserver;
34 import org.onap.ccsdk.features.sdnr.wt.common.configuration.filechange.IConfigChangedListener;
35 import org.onap.ccsdk.features.sdnr.wt.common.configuration.subtypes.Section;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * Representation of configuration file with section.<br>
41  * A root section is used for parameters, not assigned to a specific section.<br>
42  * The definitions of the configuration are attributes of a java class<br>
43  */
44 public class ConfigurationFileRepresentation implements IConfigChangedListener {
45
46         // constants
47         private static final Logger LOG = LoggerFactory.getLogger(ConfigurationFileRepresentation.class);
48
49         private static final long FILE_POLL_INTERVAL_MS = 1000;
50         private static final String SECTIONNAME_ROOT = "";
51         private static final String LR = "\n";
52         private static final String EMPTY = "";
53         // end of constants
54
55         // variables
56         /** Related configuration file **/
57         private final File mFile;
58         /** Monitor changes of file **/
59         private final ConfigFileObserver fileObserver;
60         /** List of sections **/
61         private final HashMap<String, Section> sections;
62         // end of variables
63
64         // constructors
65         public ConfigurationFileRepresentation(File f) {
66
67                 this.mFile = f;
68                 this.sections = new HashMap<String, Section>();
69                 try {
70                         if (!this.mFile.exists()) {
71                                 if (!this.mFile.createNewFile()) {
72                                         LOG.error("Can not create file {}", f.getAbsolutePath());
73                                 }
74                         }
75                         reLoad();
76
77                 } catch (IOException e) {
78                         LOG.error("Problem loading config file {} : {}", f.getAbsolutePath(), e.getMessage());
79                 }
80                 this.fileObserver = new ConfigFileObserver(f.getAbsolutePath(), FILE_POLL_INTERVAL_MS);
81                 this.fileObserver.start();
82                 this.fileObserver.registerConfigChangedListener(this);
83         }
84
85         public ConfigurationFileRepresentation(String configurationfile) {
86                 this(new File(configurationfile));
87         }
88         // end of constructors
89
90         // getters and setters
91         public synchronized Optional<Section> getSection(String name) {
92                 return Optional.ofNullable(sections.get(name));
93         }
94         // end of getters and setters
95
96         // private methods
97         private synchronized void reLoad() {
98                 sections.clear();
99                 addSection(SECTIONNAME_ROOT);
100                 load();
101         }
102
103         private synchronized void load() {
104                 LOG.debug("loading file {}", getMFileName());
105                 String curSectionName = SECTIONNAME_ROOT;
106                 Optional<Section> sectionOptional = this.getSection(curSectionName);
107                 Section curSection = sectionOptional.isPresent() ? sectionOptional.get() : this.addSection(curSectionName);
108                 BufferedReader br = null;
109                 try {
110                         br = new BufferedReader(new FileReader(this.mFile));
111                         for (String line; (line = br.readLine()) != null;) {
112                                 line = line.trim();
113                                 if (line.isEmpty()) {
114                                         continue;
115                                 }
116                                 if (line.startsWith("[") && line.endsWith("]")) {
117                                         curSectionName = line.substring(1, line.length() - 1);
118                                         curSection = this.addSection(curSectionName);
119                                 } else {
120                                         curSection.addLine(line);
121                                 }
122                         }
123
124                 } catch (Exception e) {
125                         LOG.info("Problem loading configuration file. {} {}", getMFileName(), e);
126                 } finally {
127                         try {
128                                 if (br != null) {
129                                         br.close();
130                                 }
131                         } catch (IOException e) {
132                         }
133                 }
134                 LOG.debug("finished loading file");
135                 LOG.debug("start parsing sections");
136                 for (Section section : this.sections.values()) {
137                         section.parseLines();
138                 }
139                 LOG.debug("finished parsing " + this.sections.size() + " sections");
140         }
141
142         private String getMFileName() {
143                 return mFile.getAbsolutePath();
144         }
145
146         // end of private methods
147
148         // public methods
149         public synchronized Section addSection(String name) {
150                 if (this.sections.containsKey(name)) {
151                         return this.sections.get(name);
152                 }
153                 Section s = new Section(name);
154                 this.sections.put(name, s);
155                 return s;
156         }
157
158         public synchronized void save() {
159                 LOG.debug("Write configuration to {}", getMFileName());
160                 try (BufferedWriter bw = new BufferedWriter(new FileWriter(this.mFile, false))) {
161                         for (Section section : this.sections.values()) {
162                                 if (section.hasValues()) {
163                                         bw.write(String.join(LR, section.toLines()) + LR + LR);
164                                 }
165                         }
166                         bw.close();
167                 } catch (Exception e) {
168                         LOG.warn("problem saving value: " + e.getMessage());
169                 }
170         }
171
172         public void registerConfigChangedListener(IConfigChangedListener l) {
173                 this.fileObserver.registerConfigChangedListener(l);
174         }
175
176         public void unregisterConfigChangedListener(IConfigChangedListener l) {
177                 this.fileObserver.unregisterConfigChangedListener(l);
178         }
179
180         @Override
181         public void onConfigChanged() {
182                 LOG.debug("Reload on change {}", getMFileName());
183                 reLoad();
184         }
185
186         @Override
187         public String toString() {
188                 return "ConfigurationFileRepresentation [mFile=" + mFile + ", sections=" + sections + "]";
189         }
190
191         @Override
192         protected void finalize() throws Throwable {
193                 if (this.fileObserver != null) {
194                         this.fileObserver.interrupt();
195                 }
196                 super.finalize();
197         }
198
199         /*
200          * Property access set/get
201          */
202         public synchronized void setProperty(String section, String key, Object value) {
203                 Optional<Section> os = this.getSection(section);
204                 if (os.isPresent()) {
205                         os.get().setProperty(key, value == null ? "null" : value.toString());
206                         save();
207                 } else {
208                         LOG.info("Unknown configuration section {}", section);
209                 }
210         }
211
212         public synchronized String getProperty(String section, String propertyKey) {
213                 Optional<Section> os = this.getSection(section);
214                 if (os.isPresent()) {
215                         return os.get().getProperty(propertyKey);
216                 } else {
217                         LOG.debug("Unknown configuration section {}", section);
218                         return EMPTY;
219                 }
220         }
221
222         public synchronized Optional<Long> getPropertyLong(String section, String propertyKey) {
223                 Optional<Section> os = this.getSection(section);
224                 if (os.isPresent()) {
225                         return os.get().getLong(propertyKey);
226                 } else {
227                         LOG.debug("Unknown configuration section {}", section);
228                         return Optional.empty();
229                 }
230         }
231
232         public synchronized boolean isPropertyAvailable(String section, String propertyKey) {
233                 Optional<Section> s = this.getSection(section);
234                 return s.isPresent() && s.get().hasKey(propertyKey);
235         }
236
237         public synchronized void setPropertyIfNotAvailable(String section, String propertyKey, Object propertyValue) {
238                 if (!isPropertyAvailable(section, propertyKey)) {
239                         setProperty(section, propertyKey, propertyValue.toString());
240                 }
241         }
242
243         public synchronized boolean getPropertyBoolean(String section, String propertyKey) {
244                 return getProperty(section, propertyKey).equalsIgnoreCase("true");
245         }
246         // end of public methods
247
248 }