1 /*******************************************************************************
 
   2  * ============LICENSE_START========================================================================
 
   3  * ONAP : ccsdk feature sdnr wt
 
   4  * =================================================================================================
 
   5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
 
   6  * =================================================================================================
 
   7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 
   8  * in compliance with the License. You may obtain a copy of the License at
 
  10  * http://www.apache.org/licenses/LICENSE-2.0
 
  12  * Unless required by applicable law or agreed to in writing, software distributed under the License
 
  13  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 
  14  * or implied. See the License for the specific language governing permissions and limitations under
 
  16  * ============LICENSE_END==========================================================================
 
  17  ******************************************************************************/
 
  18 package org.onap.ccsdk.features.sdnr.wt.common.configuration;
 
  20 import java.io.BufferedReader;
 
  21 import java.io.BufferedWriter;
 
  23 import java.io.FileReader;
 
  24 import java.io.FileWriter;
 
  25 import java.io.IOException;
 
  26 import java.util.HashMap;
 
  27 import java.util.Optional;
 
  29 import org.onap.ccsdk.features.sdnr.wt.common.configuration.filechange.ConfigFileObserver;
 
  30 import org.onap.ccsdk.features.sdnr.wt.common.configuration.filechange.IConfigChangedListener;
 
  31 import org.onap.ccsdk.features.sdnr.wt.common.configuration.subtypes.Section;
 
  32 import org.slf4j.Logger;
 
  33 import org.slf4j.LoggerFactory;
 
  37  * Representation of configuration file with section.<br>
 
  38  * A root section is used for parameters, not assigned to a specific section.<br>
 
  39  * The definitions of the configuration are attributes of a java class<br>
 
  41 public class ConfigurationFileRepresentation implements IConfigChangedListener {
 
  43     private static final Logger LOG = LoggerFactory.getLogger(ConfigurationFileRepresentation.class);
 
  45     private static final long FILE_POLL_INTERVAL_MS = 1000;
 
  46     private static final String SECTIONNAME_ROOT = "";
 
  47     private static final String LR = "\n";
 
  48     private static final String EMPTY = "";
 
  50     /** Related configuration file **/
 
  51     private final File mFile;
 
  52     /** Monitor changes of file **/
 
  53     private final ConfigFileObserver fileObserver;
 
  54     /** List of sections **/
 
  55     private final HashMap<String, Section> sections;
 
  57     public ConfigurationFileRepresentation(File f) {
 
  60             this.sections = new HashMap<String, Section>();
 
  62                 if (!this.mFile.exists()) {
 
  63                                 if (!this.mFile.createNewFile()) {
 
  64                                         LOG.error("Can not create file {}", f.getAbsolutePath());
 
  69                 } catch (IOException e) {
 
  70                         LOG.error("Problem loading config file {} : {}", f.getAbsolutePath(), e.getMessage());
 
  72             this.fileObserver = new ConfigFileObserver(f.getAbsolutePath(), FILE_POLL_INTERVAL_MS);
 
  73             this.fileObserver.start();
 
  74             this.fileObserver.registerConfigChangedListener(this);
 
  77         public ConfigurationFileRepresentation(String configurationfile) {
 
  78                 this(new File(configurationfile));
 
  81         public Optional<Section> getSection(String name) {
 
  82                 return Optional.ofNullable(sections.get(name));
 
  85         public Section addSection(String name) {
 
  86                 if (this.sections.containsKey(name)) {
 
  87                         return this.sections.get(name);
 
  89                 Section s = new Section(name);
 
  90                 this.sections.put(name, s);
 
  94     public void reLoad() {
 
  96         addSection(SECTIONNAME_ROOT);
 
 101         LOG.debug("Write configuration to {}", getMFileName());
 
 102         try (BufferedWriter bw = new BufferedWriter(new FileWriter(this.mFile, false))) {
 
 103             for (Section section : this.sections.values()) {
 
 104                 if (section.hasValues()) {
 
 105                     bw.write(String.join(LR, section.toLines()) + LR + LR);
 
 109         } catch (Exception e) {
 
 110             LOG.warn("problem saving value: " + e.getMessage());
 
 114     public void registerConfigChangedListener(IConfigChangedListener l) {
 
 115         this.fileObserver.registerConfigChangedListener(l);
 
 118     public void unregisterConfigChangedListener(IConfigChangedListener l) {
 
 119         this.fileObserver.unregisterConfigChangedListener(l);
 
 123         public void onConfigChanged() {
 
 124                 LOG.debug("Reload on change {}", getMFileName());
 
 129         public String toString() {
 
 130                 return "ConfigurationFileRepresentation [mFile=" + mFile + ", sections=" + sections + "]";
 
 134     protected void finalize() throws Throwable {
 
 135         if (this.fileObserver != null) {
 
 136             this.fileObserver.interrupt();
 
 142          * Property access set/get
 
 144     public void setProperty(String section, String key, Object value) {
 
 145         Optional<Section> os = this.getSection(section);
 
 146         if (os.isPresent()) {
 
 147                 os.get().setProperty(key, value == null ? "null" : value.toString());
 
 150                         LOG.info("Unknown configuration section {}", section);
 
 154         public String getProperty(String section, String propertyKey) {
 
 155         Optional<Section> os = this.getSection(section);
 
 156         if (os.isPresent()) {
 
 157                 return os.get().getProperty(propertyKey);
 
 159                         LOG.debug("Unknown configuration section {}", section);
 
 164         public Optional<Long> getPropertyLong(String section, String propertyKey) {
 
 165         Optional<Section> os = this.getSection(section);
 
 166         if (os.isPresent()) {
 
 167                 return os.get().getLong(propertyKey);
 
 169                         LOG.debug("Unknown configuration section {}", section);
 
 170                         return Optional.empty();
 
 174         public boolean isPropertyAvailable(String section, String propertyKey) {
 
 175         Optional<Section> s = this.getSection(section);
 
 176         return s.isPresent() && s.get().hasKey(propertyKey);
 
 179         public void setPropertyIfNotAvailable(String section, String propertyKey,
 
 180                         Object propertyValue) {
 
 181                 if (! isPropertyAvailable(section, propertyKey)) {
 
 182                         setProperty(section, propertyKey, propertyValue.toString());
 
 186         public boolean getPropertyBoolean(String section, String propertyKey) {
 
 187                 return getProperty(section, propertyKey).equalsIgnoreCase("true");
 
 193         private void load() {
 
 194                 LOG.debug("loading file {}", getMFileName());
 
 195                 String curSectionName = SECTIONNAME_ROOT;
 
 196                 Optional<Section> sectionOptional = this.getSection(curSectionName);
 
 197                 Section curSection=sectionOptional.isPresent()?sectionOptional.get():this.addSection(curSectionName);
 
 198                 BufferedReader br = null;
 
 200                         br = new BufferedReader(new FileReader(this.mFile));
 
 201                         for (String line; (line = br.readLine()) != null;) {
 
 203                                 if (line.isEmpty()) {
 
 206                                 if (line.startsWith("[") && line.endsWith("]")) {
 
 207                                         curSectionName = line.substring(1, line.length() - 1);
 
 208                                         curSection = this.addSection(curSectionName);
 
 210                                         curSection.addLine(line);
 
 214                 } catch (Exception e) {
 
 215                         LOG.info("Problem loading configuration file. {} {}", getMFileName(), e);
 
 221                         } catch (IOException e) {
 
 224                 LOG.debug("finished loading file");
 
 225                 LOG.debug("start parsing sections");
 
 226                 for (Section section : this.sections.values()) {
 
 227                         section.parseLines();
 
 229                 LOG.debug("finished parsing " + this.sections.size() + " sections");
 
 232     private String getMFileName() {
 
 233         return mFile.getAbsolutePath();