All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.cisco.oss.foundation.configuration.ConfigResourcesLoader Maven / Gradle / Ivy

Go to download

This project is the implementation library for configuration in the cisco vss foundation runtime

There is a newer version: 1.0.5-1
Show newest version
/*
 * Copyright 2015 Cisco Systems, Inc.
 *
 *  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.
 */

package com.cisco.oss.foundation.configuration;

import com.cisco.oss.foundation.logging.ApplicationStateInterface;
import com.cisco.oss.foundation.logging.FoundationLevel;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

import java.io.IOException;
import java.net.URL;
import java.util.*;

/**
 * returns a list of resources that could be used:
 * 

* By Spring - PropertyPlaceholderConfigurer to replace the ${param} information * inside the spring xmls. *

* By the Common configuration Loader in order to create a common configuration * object. This is a Dynamic Proxy that exposes itself as a List. it is an * external class and should not be constructed outside of CABConfiguration. *

* The implementation of this class represents the 3 basic configuration layers: *
* 1. customer layer - represented by the file: config.proeprties.
* 2. deployment layer - represented by the file: deploymentConfig.properties.
* 3. factory layer - represented by the files: defaultConfig.properties.
* the precedence of the configuration files is from 1 to 3. customer is the * strongest and factory is the weakest. * * @author Joel Gurfinkel * @author Yair Ogen */ public class ConfigResourcesLoader implements FactoryBean>, ApplicationContextAware, InitializingBean { /** * */ private static final String CUSTOMER_CONFIG = "config.properties"; /** * */ private static final String CONFIGURATION_TEST_CLASS = "com.cisco.oss.foundation.test.util.ConfigurationForTest"; /** * */ private static final String TEST_CONFIG_FILE = "testConfigFile"; private static final Logger LOGGER = LoggerFactory.getLogger(ConfigResourcesLoader.class); private static boolean LOAD_CONFIG_FROM_WORKING_DIR = Boolean.getBoolean("configuration.loadConfigFromWorkingDir"); private static boolean printedToLog = false; private final List resourcesList = new ArrayList(); private ApplicationContext context; private String internalPropertyConfig; private String internalXmlConfig; private List customerPropertyConfig; public static List customerPropertyNames = new ArrayList<>(); private List deploymentConfig; private ApplicationStateInterface applicationState; /** * set by injection the factory layer config file name. * * @param internalPropertyConfig the factory layer config file name. */ public void setInternalPropertyConfig(final String internalPropertyConfig) { this.internalPropertyConfig = internalPropertyConfig; } /** * set by injection the factory layer config file name. * * @param internalXmlConfig the factory layer xml config file name. */ public void setInternalXmlConfig(final String internalXmlConfig) { this.internalXmlConfig = internalXmlConfig; } /** * set by injection the list of all possible customer layer config file * names. * * @param customerConfig list of all possible customer layer config file names. */ public void setCustomerConfig(final List customerConfig) { this.customerPropertyConfig = customerConfig; } /** * set by injection the list of all possible deployment layer config file * names. * * @param deploymentConfig list of all possible deployment layer config file names. */ public void setDeploymentConfig(final List deploymentConfig) { this.deploymentConfig = deploymentConfig; } /** * return the list created by this dynamic proxy class. this is the list of * all the created resources of all configuration files from all * configuration layers. * * @see org.springframework.beans.factory.FactoryBean#getObject() */ @Override public List getObject() throws Exception { // NOPMD return resourcesList; } /** * return the exposed interface of this Dynamic Proxy. * * @see org.springframework.beans.factory.FactoryBean#getObjectType() */ @Override @SuppressWarnings({"rawtypes"}) public Class getObjectType() { return List.class; } /** * this is a singleton. * * @see org.springframework.beans.factory.FactoryBean#isSingleton() */ @Override public boolean isSingleton() { return true; } /** * get by injection an application context. this is a callback method * invoked by spring. * * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) */ @Override public void setApplicationContext(final ApplicationContext context) throws BeansException { this.context = context; } public void setApplicationState(ApplicationStateInterface applicationState) { this.applicationState = applicationState; } /** * fill the resourcesList only once. return it in the getObject method. */ @Override public void afterPropertiesSet() throws Exception { // NOPMD final boolean isQCEnabld = isQCEnabled(); // iterator over the list of possible external resources // only one of the resources should exist // this is to support special locations on special modules such as: Web // etc. Resource customerPropertyResource = null; // Resource customerXmlResource = null; Resource deploymentResource = null; Resource qcResource = null; if (isQCEnabld) { LOGGER.info("Found the ConfigurationTest class indicating that QC config is to be used instead of deployment and customer config files!"); qcResource = validateQCResource(); } else { customerPropertyResource = validateCustomerPropertyConfig(); deploymentResource = validateDeploymentConfig(); if (!printedToLog) { StringBuffer logMessageBuffer = new StringBuffer("The customer resources loaded are:"); printResourcesLoaded(logMessageBuffer, customerPropertyResource); if(applicationState != null){ applicationState.setState(FoundationLevel.INFO, logMessageBuffer.toString()); } if (deploymentResource != null) { logMessageBuffer = new StringBuffer("The deployment resources loaded are:"); printResourcesLoaded(logMessageBuffer, deploymentResource); if(applicationState != null) { applicationState.setState(FoundationLevel.INFO, logMessageBuffer.toString()); } } } } // get all the resources of the internal property config files. final Resource[] internalPropertyResources = context.getResources(internalPropertyConfig); final List internalPropertyResourcesList = Arrays.asList(internalPropertyResources); // get all the resources of the internal xml config files. // xml resources take precedence over the properties loaded. final Resource[] internalXmlResources = context.getResources(internalXmlConfig); final List internalXmlResourcesList = Arrays.asList(internalXmlResources); if (!printedToLog) { final StringBuffer logMessageBuffer = new StringBuffer("The default resources loaded are:"); printResourcesLoaded(logMessageBuffer, internalXmlResourcesList); printResourcesLoaded(logMessageBuffer, internalPropertyResourcesList); if(applicationState != null) { applicationState.setState(FoundationLevel.INFO, logMessageBuffer.toString()); } printedToLog = true; } // order of the resources is important to maintain properly the // hierarchy of the configuration. resourcesList.addAll(internalPropertyResourcesList); // xml resources take precedence over the properties loaded. resourcesList.addAll(internalXmlResourcesList); if (deploymentResource != null) { resourcesList.add(deploymentResource); } if (customerPropertyResource != null) { resourcesList.add(customerPropertyResource); } // xml customer resource take precedence over the properties loaded. // if (customerXmlResource != null) { // resourcesList.add(customerXmlResource); // } if (qcResource != null) { resourcesList.add(qcResource); } } /** * @return */ private Resource validateQCResource() { Resource qcResource = null; String qcFile = System.getProperty(TEST_CONFIG_FILE); if (StringUtils.isBlank(qcFile)) { // throw new // IllegalArgumentException("Application was started with the " + // CONFIGURATION_TEST_CLASS + // " in the class path, but the system property: " + // TEST_CONFIG_FILE + " was not found!"); // in order to support tests that do not wish to set the test // property while other do, we fallback to the default // "config.proeprties" file in case the system property is empty. qcFile = CUSTOMER_CONFIG; } // validate the file name. it must contain a case less "test" word in // it. if (!qcFile.equals(CUSTOMER_CONFIG) && !qcFile.matches(".*(?i)test(?-i).*")) { throw new IllegalArgumentException("The test config file name is not valid. it must containt the word 'test' in it, but it does not. the file names processed is: " + qcFile); } LOGGER.debug("searching for the file name: " + qcFile); qcResource = new ClassPathResource(qcFile); return qcResource; } /** * @return */ private boolean isQCEnabled() { boolean isQCEnabled = true; try { Class.forName(CONFIGURATION_TEST_CLASS); } catch (ClassNotFoundException e) { isQCEnabled = false; } return isQCEnabled; } private Resource validateCustomerPropertyConfig() { Resource customerResource = null; boolean isValid = false; for (String resource : customerPropertyConfig) { customerResource = context.getResource(resource); isValid = validateResourceIsValid(customerResource); if (isValid) { // the first valid resource will be used. break; } } if (Boolean.valueOf(System.getenv(CcpConstants.CCP_ENABLED))) { customerResource = null; } else if (!isValid && !customerResource.getFilename().contains("dummyConfig")) { if (LOAD_CONFIG_FROM_WORKING_DIR) { FileSystemResource fileSystemResource = new FileSystemResource("config.properties"); isValid = validateResourceIsValid(fileSystemResource); if (!isValid) { LOGGER.error("could not find the file: " + fileSystemResource.getFilename()); return null; } else { customerResource = fileSystemResource; } } else { if (!"config.properties".equals(customerResource.getFilename())) { customerResource = context.getResource("classpath:/config.properties"); isValid = validateResourceIsValid(customerResource); if (!isValid) { LOGGER.error("could not find the file: " + customerResource.getFilename()); return null; } } else { LOGGER.error("could not find the file: " + customerResource.getFilename()); // for backward compatibility do not mandate this file. return null; } } } if(customerResource != null){ try { URL customerResourceURL = customerResource.getURL(); if (customerResourceURL != null) { Properties properties = new Properties(); properties.load(customerResourceURL.openStream()); ArrayList list = Collections.list(properties.propertyNames()); for (Object propName : list) { customerPropertyNames.add(propName.toString()); } } } catch (IOException e) { LOGGER.error("can't read customer url", e); } } return customerResource; } private Resource validateDeploymentConfig() { if (deploymentConfig == null) { return null; } else { Resource deploymentResource = null; boolean isValid = false; for (String resource : deploymentConfig) { deploymentResource = context.getResource(resource); isValid = validateResourceIsValid(deploymentResource); if (isValid) { // the first valid resource will be used. break; } } if (!isValid) { LOGGER.trace("Could not find the file: deploymentConfig.properties in the class path"); return null; } return deploymentResource; } } /** * Make sure the URL is correct and exists. used to support different * locations for a resources (E.g. under WEB-INF or not etc.) * * @param externalResource the resource to check it's validity. * @return true if exists, false if not. */ private boolean validateResourceIsValid(final Resource externalResource) { boolean isValid = true; try { URL url = externalResource.getURL(); if (url.getPath() != null && url.getPath().contains(".jar") && !url.getPath().contains("dummyConfig")) { throw new IllegalArgumentException("The customer config file: \"config.properties\" was found in a jar file. This is not legal. Offending jar is: " + url.getPath()); } } catch (IOException e) { isValid = false; } return isValid; } private void printResourcesLoaded(final StringBuffer logMessageBuffer, final Resource resource) throws IOException { if (resource == null) { LOGGER.debug("Loaded a null resource in the resources list"); } else { logMessageBuffer.append('\n'); logMessageBuffer.append(resource.getURL()).append(" config file loaded"); } } private void printResourcesLoaded(final StringBuffer logMessageBuffer, final List resourcesList) throws IOException { for (Resource resource : resourcesList) { printResourcesLoaded(logMessageBuffer, resource); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy