/******************************************************************************* * Copyright 2012 Pradeep Nambiar, Pexus LLC * * Source File: src/org/perf/log/utils/PropertyFileLoader.java * * 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. ******************************************************************************/ /* * This class loads property files and provides flexibility to load the file * if one is included with in the application's class path before trying to load * a propety from the parent's class path. It also gives an option to load * default property file if the specified property file is not found */ package org.perf.log.utils; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Enumeration; import java.util.HashMap; import java.util.Properties; public class PropertyFileLoader { // Hash map of properties file already loaded // Key is the full url path of the property file static HashMap<String, Properties> cachedProperties = new HashMap<String, Properties>(); static int maxCachedPropertiesHashMapSize = 50; // This method loads the default set of properties first // Then it loads the overriding properties file // It returns the merged properties to the caller and also caches the returned properties public static Properties load( String overridingPropertyFileName, String defaultPropertyFileName, ClassLoader ctxClassLoader, ClassLoader callingClassLoader, String callingClassName) { InputStream inDefaultPropertiesStream = null; InputStream inOverridingPropertiesStream = null; URL urlForTheDefaultPropertiesLoaded = null; URL urlForTheOverridingPropertiesLoaded = null; // First try to get the input stream for default properties using the defaultPropertyFileName using the callingClassLoader if (callingClassLoader != null) { inDefaultPropertiesStream = callingClassLoader.getResourceAsStream(defaultPropertyFileName); urlForTheDefaultPropertiesLoaded = callingClassLoader.getResource(defaultPropertyFileName); } // Next try to get the input stream for overriding properties using overridingPropertyFileName // using the context class loader if (ctxClassLoader != null) { inOverridingPropertiesStream = ctxClassLoader.getResourceAsStream(overridingPropertyFileName); if (inOverridingPropertiesStream != null) urlForTheOverridingPropertiesLoaded = ctxClassLoader.getResource(overridingPropertyFileName); } if (inDefaultPropertiesStream == null && inOverridingPropertiesStream == null) { System.out.println(PropertyFileLoader.class.getName() + ":Error loading " + defaultPropertyFileName + " and " + overridingPropertyFileName + " properties files"); return null; } // else check cache for the same set of properties already loaded or load properties and return the properties String cacheKey = null; if(inDefaultPropertiesStream !=null && inOverridingPropertiesStream != null) cacheKey = urlForTheDefaultPropertiesLoaded.getPath() + " + " + urlForTheOverridingPropertiesLoaded.getPath(); else if(inDefaultPropertiesStream == null) cacheKey = urlForTheOverridingPropertiesLoaded.getPath(); else if(inOverridingPropertiesStream == null) cacheKey = urlForTheDefaultPropertiesLoaded.getPath(); Properties props = null; try { // Check if the property file already loaded and cached.. if ((props = cachedProperties.get(cacheKey)) != null) { System.out.println(PropertyFileLoader.class.getName() + ":" + cacheKey + " properties already loaded, returning from cache."); } else { props = new Properties(); if(inDefaultPropertiesStream != null) { props.load(inDefaultPropertiesStream); System.out.println(PropertyFileLoader.class.getName() + ":Loading properties from:" + urlForTheDefaultPropertiesLoaded.getPath()); } if(inOverridingPropertiesStream != null) { props.load(inOverridingPropertiesStream); System.out.println(PropertyFileLoader.class.getName() + ":Overriding properties from:" + urlForTheOverridingPropertiesLoaded.getPath()); } System.out.println("------------ Merged Properties -----"); Enumeration <Object> keys = props.keys(); while(keys.hasMoreElements()) { String key = (String)keys.nextElement(); System.out.println( key + " = " + props.get(key)); } System.out.println("------------------------------------"); // Put the loaded property in the cache if(cachedProperties.size()>=maxCachedPropertiesHashMapSize) cachedProperties.clear(); // and start over again cachedProperties.put(cacheKey, props); } } catch (IOException e) { System.out.println(PropertyFileLoader.class.getName() + ":IO Exception loading property file: " + cacheKey); } return props; } }