diff options
Diffstat (limited to 'appc-core/appc-common-bundle/java/org/onap/appc/configuration/ConfigurationFactory.java')
-rw-r--r-- | appc-core/appc-common-bundle/java/org/onap/appc/configuration/ConfigurationFactory.java | 433 |
1 files changed, 0 insertions, 433 deletions
diff --git a/appc-core/appc-common-bundle/java/org/onap/appc/configuration/ConfigurationFactory.java b/appc-core/appc-common-bundle/java/org/onap/appc/configuration/ConfigurationFactory.java deleted file mode 100644 index 9ea5083fe..000000000 --- a/appc-core/appc-common-bundle/java/org/onap/appc/configuration/ConfigurationFactory.java +++ /dev/null @@ -1,433 +0,0 @@ -/*- - * ============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. - * <p> - * 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 - * <code>Configuration</code> interface. This allows for the factory to create different - * specializations in the future if needed and not break any application code. - * </p> - * <p> - * 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). - * </p> - * <p> - * Since the configuration is managed as a property object, we can use a characteristic of the - * <code>Properties</code> class to our advantage. Namely, if we put a property into a - * <code>Properties</code> object that already exists, the <code>Properties</code> 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. - * </p> - * <p> - * 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: - * </p> - * <ol> - * <li>Default values from a system resource file.</li> - * <li>User-supplied properties file, if any.</li> - * <li>Application-supplied properties, if any.</li> - * <li>Command-line properties (if any)</li> - * </ol> - * <p> - * 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: - * </p> - * <dl> - * <dt>org.onap.appc.bootstrap.file</dt> - * <dd>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.</dd> - * <dt>org.onap.appc.bootstrap.path</dt> - * <dd>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 <code>$/opt/onap/appc/data/properties,${user.home},.</code></dd> - * </dl> - * - * @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 <code>Configuration</code> 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<Object, Configuration> localConfigs = new HashMap<>(); - - /** - * The reentrant shared lock used to serialize access to the properties. - */ - private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - - /** - * This is a constant array of special property names that will be copied from the configuration - * back to the System properties object if they are defined in the configuration AND they do not - * already exist in the System properties object. These are intended as a convenience for - * setting the AFT properties for the Discovery client where it may be difficult or impossible - * to set VM arguments for the container. - */ - private static final String[] specialProperties = - {"AFT_LATITUDE", "AFT_LONGITUDE", "AFT_ENVIRONMENT", "SCLD_PLATFORM"}; - - private ConfigurationFactory() {} - - /** - * This method is used to obtain the common configuration object (as well as set it up if not - * already). - * - * @return The configuration object implementation - */ - public static Configuration getConfiguration() { - - /* - * First, attempt to access the properties as a read lock holder - */ - ReadLock readLock = lock.readLock(); - readLock.lock(); - try { - - /* - * If the properties don't exist, release the read lock and acquire the write lock. Once - * we get the write lock, we need to re-check to see that the configuration needs to be - * set up (because another thread may have beat us to it). After we get a configuration - * set up, release the write lock and re-obtain the read lock to access the properties. - */ - if (config == null) { - readLock.unlock(); - WriteLock writeLock = lock.writeLock(); - writeLock.lock(); - try { - if (config == null) { - config = new DefaultConfiguration(); - initialize(null); - } - } catch (Exception e){ - logger.error("getConfiguration", e); - } finally { - writeLock.unlock(); - } - readLock.lock(); - } - } finally { - readLock.unlock(); - } - return config; - } - - /** - * This method will obtain the local configuration for the specified object if it exists, or - * will create it from the current global configuration. This allows the configuration to be - * tailored for a specific process or operation, and uniquely identified by some value (such as - * the object that represents the special use of the configuration). - * - * @param owner The owner or identification of the owner of the special configuration - * @return The special configuration object, or a clone of the global configuration so that it - * can be altered if needed. - */ - public static Configuration getConfiguration(final Object owner) { - DefaultConfiguration local; - ReadLock readLock = lock.readLock(); - readLock.lock(); - try { - local = (DefaultConfiguration) localConfigs.get(owner); - if (local == null) { - readLock.unlock(); - WriteLock writeLock = lock.writeLock(); - writeLock.lock(); - local = (DefaultConfiguration) localConfigs.get(owner); - if (local == null) { - local = getClonedDefaultConfiguration(owner, local); - } - writeLock.unlock(); - } - readLock.lock(); - } finally { - readLock.unlock(); - } - return local; - } - - /** - * This method allows the caller to alter the configuration, supplying the specified - * configuration properties which override the application default values. - * <p> - * The configuration is re-constructed (if already constructed) or created new (if not already - * created) and the default properties are loaded into the configuration. - * </p> - * <p> - * The primary purpose of this method is to allow the application configuration properties to be - * reset or refreshed after the application has already been initialized. This method will lock - * the configuration for the duration while it is being re-built, and should not be called on a - * regular basis. - * </p> - * - * @param props The properties used to configure the application. - * @return Access to the configuration implementation - */ - public static Configuration getConfiguration(final Properties props) { - WriteLock writeLock = lock.writeLock(); - writeLock.lock(); - try { - config = new DefaultConfiguration(); - initialize(props); - return config; - } finally { - writeLock.unlock(); - } - } - - private static DefaultConfiguration getClonedDefaultConfiguration(Object owner, DefaultConfiguration local) { - Optional<DefaultConfiguration> global = - Optional.ofNullable((DefaultConfiguration) getConfiguration()); - try { - if (global.isPresent()) { - local = (DefaultConfiguration) global.get().clone(); - } - } catch (CloneNotSupportedException e) { - logger.error("getClonedDefaultConfiguration", e); - } - localConfigs.put(owner, local); - return local; - } - - /** - * This method will clear the current configuration and then re-initialize it with the default - * values, application-specific configuration file, user-supplied properties (if any), and then - * command-line settings. - * <p> - * This method <strong><em>MUST</em></strong> be called holding the configuration lock! - * </p> - * <p> - * This method is a little special in that logging messages generated during the method must be - * cached and delayed until after the logging framework has been initialized. After that, the - * delayed logging buffer can be dumped to the log file and cleared. - * </p> - * - * @param props Application-supplied configuration values, if any - */ - private static void initialize(final Properties props) { - DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); - Date now = new Date(); - logger.info( - "------------------------------------------------------------------------------"); - - logger.info(Msg.CONFIGURATION_STARTED, format.format(now)); - - /* - * Clear any existing properties - */ - config.clear(); - logger.info(Msg.CONFIGURATION_CLEARED); - - /* - * Load the defaults (if any are present) - */ - InputStream in = Thread.currentThread().getContextClassLoader() - .getResourceAsStream(DEFAULT_PROPERTIES); - if (in != null) { - logger.info(Msg.LOADING_DEFAULTS, DEFAULT_PROPERTIES); - try { - config.setProperties(in); - } finally { - try { - in.close(); - } catch (IOException e) { - logger.error("Cannot close inputStream", e); - } - } - for (String key : config.getProperties().stringPropertyNames()) { - logger.info(Msg.PROPERTY_VALUE, key, config.getProperty(key)); - } - } else { - logger.info(Msg.NO_DEFAULTS_FOUND, DEFAULT_PROPERTIES); - } - - /* - * Look for application configuration property file. By default, we will look for the file - * "cdp.properties" on the user home path, then on "./etc" (relative to current path), then - * on "../etc" (relative to current path). If we do not find any property file, then we - * continue. Otherwise, we load the first property file we find and then continue. In order - * to allow default values for the filename and paths to be searched, we first attempt to - * obtain these from our configuration object (which should be primed with default values - * and/or overridden with application-specified values). We then use the values obtained - * from that to get any user supplied values on the command line. - */ - String filename = config.getProperty(Configuration.PROPERTY_BOOTSTRAP_FILE_NAME, - Configuration.DEFAULT_BOOTSTRAP_FILE_NAME); - filename = System.getProperty(Configuration.PROPERTY_BOOTSTRAP_FILE_NAME, filename); - String env = System.getenv(Configuration.PROPERTY_BOOTSTRAP_FILE_NAME); - if (env != null && env.trim().length() > 0) { - filename = env; - } - - String path = config.getProperty(Configuration.PROPERTY_BOOTSTRAP_FILE_PATH, - Configuration.DEFAULT_BOOTSTRAP_FILE_PATH); - path = System.getProperty(Configuration.PROPERTY_BOOTSTRAP_FILE_PATH, path); - env = System.getenv(Configuration.PROPERTY_BOOTSTRAP_FILE_PATH); - if (env != null && env.trim().length() > 0) { - path = env; - } - - logger.info(Msg.SEARCHING_CONFIGURATION_OVERRIDES, path, filename); - - String[] pathElements = path.split(COMMA); - boolean found = false; - for (String pathElement : pathElements) { - File file = new File(pathElement, filename); - if (file.exists() && file.canRead() && !file.isDirectory()) { - - logger.info(Msg.LOADING_CONFIGURATION_OVERRIDES, file.getAbsolutePath()); - Properties fileProperties = new Properties(); - BufferedInputStream stream = null; - try { - stream = new BufferedInputStream(new FileInputStream(file)); - fileProperties.load(stream); - for (String key : fileProperties.stringPropertyNames()) { - logger.debug(Msg.PROPERTY_VALUE, key, fileProperties.getProperty(key)); - config.setProperty(key, fileProperties.getProperty(key)); - } - found = true; - break; - } catch (IOException e) { - logger.error(EELFResourceManager.format(e)); - } finally { - try { - if (stream != null) { - stream.close(); - } - } catch (IOException e) { - logger.error("Unable to close stream", e); - } - } - } - } - - if (!found) { - logger.warn(Msg.NO_OVERRIDE_PROPERTY_FILE_LOADED, filename, path); - } - - /* - * Apply any application-specified properties - */ - if (props != null) { - logger.info(Msg.LOADING_APPLICATION_OVERRIDES); - for (String key : props.stringPropertyNames()) { - logger.debug(Msg.PROPERTY_VALUE, key, props.getProperty(key)); - config.setProperty(key, props.getProperty(key)); - } - } else { - logger.info(Msg.NO_APPLICATION_OVERRIDES); - } - - /* - * Merge in the System.properties to pick-up any command line arguments (-Dkeyword=value) - */ - logger.info(Msg.MERGING_SYSTEM_PROPERTIES); - config.setProperties(System.getProperties()); - - /* - * As a convenience, copy the "specialProperties" that are not defined in System.properties - * from the configuration back to the system properties object. - */ - for (String key : config.getProperties().stringPropertyNames()) { - for (String specialProperty : specialProperties) { - if (key.equals(specialProperty) && !System.getProperties().containsKey(key)) { - System.setProperty(key, config.getProperty(key)); - logger.info(Msg.SETTING_SPECIAL_PROPERTY, key, config.getProperty(key)); - } - } - } - - /* - * Initialize the resource manager by loading the requested bundles, if any are defined. - * Resource bundles may be specified as a comma-delimited list of names. These resource - * names are base names of resource bundles, do not include the language or country code, or - * the ".properties" extension. The actual loading of the resource bundles is done lazily - * when requested the first time. If the bundle does not exist, or cannot be loaded, it is - * ignored. - */ - String resourcesList = config.getProperty(Configuration.PROPERTY_RESOURCE_BUNDLES, - Configuration.DEFAULT_RESOURCE_BUNDLES); - String[] resources = resourcesList.split(","); - for (String resource : resources) { - logger.info(Msg.LOADING_RESOURCE_BUNDLE, resource.trim()); - EELFResourceManager.loadMessageBundle(resource.trim()); - } - } -} |