2 * ============LICENSE_START=======================================================
3 * ONAP : ccsdk features
4 * ================================================================================
5 * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
22 package org.onap.ccsdk.features.sdnr.wt.common.configuration;
24 import java.io.BufferedReader;
25 import java.io.BufferedWriter;
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 import org.onap.ccsdk.features.sdnr.wt.common.configuration.filechange.ConfigFileObserver;
33 import org.onap.ccsdk.features.sdnr.wt.common.configuration.filechange.IConfigChangedListener;
34 import org.onap.ccsdk.features.sdnr.wt.common.configuration.subtypes.Section;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
39 * Representation of configuration file with section.<br>
40 * A root section is used for parameters, not assigned to a specific section.<br>
41 * The definitions of the configuration are attributes of a java class<br>
43 public class ConfigurationFileRepresentation implements IConfigChangedListener {
46 private static final Logger LOG = LoggerFactory.getLogger(ConfigurationFileRepresentation.class);
48 private static final long FILE_POLL_INTERVAL_MS = 1000;
49 public static final String SECTIONNAME_ROOT = "";
50 private static final String LR = "\n";
51 private static final String EMPTY = "";
55 /** Related configuration file **/
56 private final File mFile;
57 /** Monitor changes of file **/
58 private final ConfigFileObserver fileObserver;
59 /** List of sections **/
60 private final HashMap<String, Section> sections;
64 public ConfigurationFileRepresentation(File f) {
67 this.sections = new HashMap<String, Section>();
69 if (!this.mFile.exists()) {
70 if (!this.mFile.createNewFile()) {
71 LOG.error("Can not create file {}", f.getAbsolutePath());
73 this.mFile.setReadable(true, false);
74 this.mFile.setWritable(true, false);
78 } catch (IOException e) {
79 LOG.error("Problem loading config file {} : {}", f.getAbsolutePath(), e.getMessage());
81 this.fileObserver = new ConfigFileObserver(f.getAbsolutePath(), FILE_POLL_INTERVAL_MS);
82 this.fileObserver.start();
83 this.fileObserver.registerConfigChangedListener(this);
86 public ConfigurationFileRepresentation(String configurationfile) {
87 this(new File(configurationfile));
89 // end of constructors
91 // getters and setters
92 public synchronized Optional<Section> getSection(String name) {
93 return Optional.ofNullable(sections.get(name));
95 // end of getters and setters
98 private synchronized void reLoad() {
100 addSection(SECTIONNAME_ROOT);
104 private synchronized void load() {
105 LOG.debug("loading file {}", getMFileName());
106 String curSectionName = SECTIONNAME_ROOT;
107 Optional<Section> sectionOptional = this.getSection(curSectionName);
108 Section curSection = sectionOptional.isPresent() ? sectionOptional.get() : this.addSection(curSectionName);
109 BufferedReader br = null;
111 br = new BufferedReader(new FileReader(this.mFile));
112 for (String line; (line = br.readLine()) != null;) {
114 if (line.isEmpty()) {
117 if (line.startsWith("[") && line.endsWith("]")) {
118 curSectionName = line.substring(1, line.length() - 1);
119 curSection = this.addSection(curSectionName);
121 curSection.addLine(line);
125 } catch (Exception e) {
126 LOG.info("Problem loading configuration file. {} {}", getMFileName(), e);
132 } catch (IOException e) {
135 LOG.debug("finished loading file");
136 LOG.debug("start parsing sections");
137 for (Section section : this.sections.values()) {
138 section.parseLines();
140 LOG.debug("finished parsing " + this.sections.size() + " sections");
143 private String getMFileName() {
144 return mFile.getAbsolutePath();
147 // end of private methods
150 public synchronized Section addSection(String name) {
151 if (this.sections.containsKey(name)) {
152 return this.sections.get(name);
154 Section s = new Section(name);
155 this.sections.put(name, s);
159 public synchronized void save() {
160 LOG.debug("Write configuration to {}", getMFileName());
161 try (BufferedWriter bw = new BufferedWriter(new FileWriter(this.mFile, false))) {
162 for (Section section : this.sections.values()) {
163 if (section.hasValues()) {
164 bw.write(String.join(LR, section.toLines()) + LR + LR);
168 } catch (Exception e) {
169 LOG.warn("problem saving value: " + e.getMessage());
173 public void registerConfigChangedListener(IConfigChangedListener l) {
174 this.fileObserver.registerConfigChangedListener(l);
177 public void unregisterConfigChangedListener(IConfigChangedListener l) {
178 this.fileObserver.unregisterConfigChangedListener(l);
182 public void onConfigChanged() {
183 LOG.debug("Reload on change {}", getMFileName());
188 public String toString() {
189 return "ConfigurationFileRepresentation [mFile=" + mFile + ", sections=" + sections + "]";
193 protected void finalize() throws Throwable {
194 if (this.fileObserver != null) {
195 this.fileObserver.interrupt();
201 * Property access set/get
203 public synchronized void setProperty(String section, String key, Object value) {
204 Optional<Section> os = this.getSection(section);
205 if (os.isPresent()) {
206 os.get().setProperty(key, value == null ? "null" : value.toString());
209 LOG.info("Unknown configuration section {}", section);
213 public synchronized String getProperty(String section, String propertyKey) {
214 Optional<Section> os = this.getSection(section);
215 if (os.isPresent()) {
216 return os.get().getProperty(propertyKey);
218 LOG.debug("Unknown configuration section {}", section);
223 public synchronized Optional<Long> getPropertyLong(String section, String propertyKey) {
224 Optional<Section> os = this.getSection(section);
225 if (os.isPresent()) {
226 return os.get().getLong(propertyKey);
228 LOG.debug("Unknown configuration section {}", section);
229 return Optional.empty();
233 public synchronized boolean isPropertyAvailable(String section, String propertyKey) {
234 Optional<Section> s = this.getSection(section);
235 return s.isPresent() && s.get().hasKey(propertyKey);
238 public synchronized void setPropertyIfNotAvailable(String section, String propertyKey, Object propertyValue) {
239 if (!isPropertyAvailable(section, propertyKey)) {
240 setProperty(section, propertyKey, propertyValue.toString());
244 public synchronized boolean getPropertyBoolean(String section, String propertyKey) {
245 return getProperty(section, propertyKey).equalsIgnoreCase("true");
247 // end of public methods