content: package com.atg.openssp.core.system.loader;
  
  import java.lang.reflect.Field;
  import java.util.Properties;
  import java.util.Set;
  import java.util.concurrent.CountDownLatch;
  
  import javax.xml.bind.PropertyException;
  
  import org.apache.commons.lang3.StringUtils;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import com.atg.openssp.common.annotation.RuntimeMeta;
  import com.atg.openssp.common.annotation.Scope;
  import com.atg.openssp.common.configuration.ContextCache;
  import com.atg.openssp.common.configuration.ContextProperties;
  import com.atg.openssp.common.watchdog.DynamicLoadable;
  
  import util.properties.ProjectProperty;
  
  /**
   * @author André Schmer
   * 
   */
  public abstract class AbstractConfigurationLoader implements DynamicLoadable {
  
  	private static final Logger log = LoggerFactory.getLogger(AbstractConfigurationLoader.class);
  
  	private Properties properties;
  	private final String propertiesFile;
  	private final CountDownLatch latch;
  
  	AbstractConfigurationLoader(final String propertiesFile) {
  		this(propertiesFile, null);
  	}
  
  	AbstractConfigurationLoader(final String propertiesFile, final CountDownLatch cdl) {
  		this.propertiesFile = propertiesFile;
  		latch = cdl;
  	}
  
  	/**
  	 * Reads the values from the properties file and loads services behind the values, if necessary.
  	 */
  	@Override
  	public void readValues() {
  		loadProperties();
  		final Set<Object> keys = properties.keySet();
  
  		for (final Object object : keys) {
  			final String key = (String) object;
  			final String value = properties.getProperty(key);
  			final ContextProperties contextProps = ContextProperties.get(key);
  			if (contextProps != null) {
  				try {
  					final Field propertyField = ContextProperties.class.getDeclaredField(contextProps.name());
  					final boolean isPrintable = propertyField.getAnnotation(RuntimeMeta.class).printable();
  					if (isPrintable) {
  						final Scope type = propertyField.getAnnotation(RuntimeMeta.class).type();
  						final String typeValue = type != null ? type.getValue() : "";
  						log.info(typeValue + ": " + contextProps + "=" + value);
  					}
  					ContextCache.instance.put(contextProps, value);
  				} catch (final NoSuchFieldException | SecurityException e) {
  					log.error(e.getMessage());
  				}
  				readSpecials(contextProps, value);
  			}
  		}
  
  		finalWork();
  		if (latch != null) {
  			latch.countDown();
  		}
  	}
  
  	@Override
  	public String getResourceFilename() {
  		return propertiesFile;
  	}
  
  	@Override
  	public String getResourceLocation() {
  		try {
  			return ProjectProperty.getPropertiesResourceLocation();
  		} catch (final PropertyException e) {
  			log.error(e.getMessage());
  		}
  		return null;
  	}
  
  	/**
  	 * Template method for special loader jobs to implement by subclass.
  	 * 
  	 * @param key
  	 * @param value
  	 */
  	protected void readSpecials(final ContextProperties key, final String value) {}
  
  	protected abstract void finalWork();
  
  	private void loadProperties() {
  		try {
  			if (StringUtils.isNotEmpty(propertiesFile)) {
  				properties = ProjectProperty.getRuntimeProperties(propertiesFile);
  			}
  		} catch (final PropertyException e) {
  			log.error(e.getMessage());
  		}
  	}
  
  }
  