/*-
* ============LICENSE_START=======================================================
* ONAP : APPC
* ================================================================================
* Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Copyright (C) 2017 Amdocs
* =============================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ============LICENSE_END=========================================================
*/
package org.onap.appc.configuration;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import org.onap.appc.i18n.Msg;
import com.att.eelf.configuration.EELFLogger;
import com.att.eelf.configuration.EELFManager;
import com.att.eelf.i18n.EELFResourceManager;
/**
* The configuration factory is used to obtain access to an already created and initialized
* singleton configuration object as well as to create and initialize the singleton if not already
* set up.
*
* This class is responsible for the creation of the configuration object used to manage the
* configuration of the application. The configuration object implementation must implement the
* Configuration interface. This allows for the factory to create different
* specializations in the future if needed and not break any application code.
*
*
* The configuration object is basically a wrapper around a properties object. The configuration is
* therefore specified as a set of properties that are loaded and processed from different sources
* with different precedences. It is important that the configuration object always be able to
* supply default values for any configuration properties that must be supplied, and not rely on the
* user always supplying these values. This also relieves the application itself from having to
* interpret missing or invalid properties and applying defaults. By having all of the defaults in
* one place, the application code can be simpler (not having to worry about defaults or invalid
* properties), and the defaults can be changed much easier (they are all in one place and not
* distributed throughout the codebase).
*
*
* Since the configuration is managed as a property object, we can use a characteristic of the
* Properties class to our advantage. Namely, if we put a property into a
* Properties object that already exists, the Properties object replaces
* it with the new value. This does not affect any other properties that may already be defined in
* the properties object. This gives us the ability to initialize the properties with default values
* for all of the application settings, then override just those that we need to override, possibly
* from multiple sources and in increasing order of precedence.
*
*
* This means that properties are in effect "merged" together from multiple sources in a prescribed
* precedence order. In fact, the precedence order that this factory implements is defined as:
*
*
*
Default values from a system resource file.
*
User-supplied properties file, if any.
*
Application-supplied properties, if any.
*
Command-line properties (if any)
*
*
* The name and location of the properties file that is loaded can also be set, either in the
* defaults, overridden by the system command line via -D, or as a system environment variable.
* There are two properties that can be specified to define the name and path. These are:
*
*
*
org.onap.appc.bootstrap.file
*
This property defines the name of the file that will be loaded. If not specified, the default
* value is "appc.properties". This can be specified in either (or both) the default properties or
* the command line. The command line specification will always override.
*
org.onap.appc.bootstrap.path
*
This is a comma-delimited (,) path of directories to be searched to locate the specified
* file. The first occurrence of the file is the one loaded, and no additional searching is
* performed. The path can be specified in either, or both, the default values and the command line
* specification. If specified on the command line, the value overrides the default values. If
* omitted, the default path is $/opt/onap/appc/data/properties,${user.home},.
*
*
* @since Mar 18, 2014
* @version $Id$
*/
public final class ConfigurationFactory {
private static final EELFLogger logger = EELFManager.getInstance().getLogger(ConfigurationFactory.class);
/**
* This is a string constant for the comma character. It's intended to be used a common string
* delimiter.
*/
private static final String COMMA = ",";
/**
* The default Configuration object that implements the Configuration interface and
* represents our system configuration settings.
*/
private static DefaultConfiguration config = null;
/**
* The default properties resource to be loaded
*/
private static final String DEFAULT_PROPERTIES = "org/onap/appc/default.properties";
/**
* This collection allows for special configurations to be created and maintained, organized by
* some identification (such as an object reference to the StackBuilder to which they apply),
* and then obtained from the configuration factory when needed.
*/
private static HashMap