001/** 002 * Copyright 2014 Tampere University of Technology, Pori Department 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package core.tut.pori.properties; 017 018import java.io.IOException; 019import java.io.InputStream; 020import java.util.Date; 021import java.util.HashMap; 022import java.util.Iterator; 023import java.util.Map; 024import java.util.Properties; 025 026import javax.servlet.ServletContext; 027 028import org.apache.log4j.Logger; 029import org.springframework.context.support.ClassPathXmlApplicationContext; 030 031import core.tut.pori.context.RESTHandler; 032import core.tut.pori.utils.StringUtils; 033 034/** 035 * The system property handler. 036 * 037 * This class can be used to retrieve system property files known by the system. 038 * 039 * One should not initialize this handler directly, as an instantiated version is available from ServiceInitializer. 040 */ 041public final class PropertyHandler { 042 private static final Logger LOGGER = Logger.getLogger(PropertyHandler.class); 043 private static final String PROPERTIES_CONFIGURATION_FILE = "properties-context.xml"; 044 /* services */ 045 private String _bindContext = null; 046 private String _restBindContext = null; 047 private ClassPathXmlApplicationContext _context = null; 048 private Map<Class<?>,SystemProperty> _properties = null; 049 050 /** 051 * @param context 052 * 053 */ 054 public PropertyHandler(ServletContext context){ 055 LOGGER.debug("Initializing handler..."); 056 Date started = new Date(); 057 _context = new ClassPathXmlApplicationContext(core.tut.pori.properties.SystemProperty.CONFIGURATION_FILE_PATH+PROPERTIES_CONFIGURATION_FILE); 058 LOGGER.debug("Class Path XML Context initialized in "+StringUtils.getDurationString(started, new Date())); 059 060 loadProperties(context); 061 LOGGER.debug("Property Handler initialized in "+StringUtils.getDurationString(started, new Date())); 062 } 063 064 /** 065 * @param context 066 * @throws IllegalArgumentException 067 */ 068 private void loadProperties(ServletContext context) throws IllegalArgumentException{ 069 ClassLoader classLoader = getClass().getClassLoader(); 070 try (InputStream systemStream = classLoader.getResourceAsStream(SystemProperty.SYSTEM_PROPERTY_FILE)) { 071 Properties systemProperties = new Properties(); 072 systemProperties.load(systemStream); 073 systemProperties = UnmodifiableProperties.unmodifiableProperties(systemProperties); 074 _bindContext = systemProperties.getProperty(SystemProperty.PROPERTY_SERVICE_PORI_PROPERTIES_BIND_ADDRESS)+context.getContextPath()+"/"; 075 _restBindContext = _bindContext + RESTHandler.PATH_REST; 076 077 Map<String, SystemProperty> propertyMap = _context.getBeansOfType(SystemProperty.class); 078 if(propertyMap == null || propertyMap.isEmpty()){ 079 LOGGER.debug("No properties to initialize."); 080 return; 081 } 082 int size = propertyMap.size(); 083 LOGGER.debug("Found "+size+" SystemProperties."); 084 085 _properties = new HashMap<>(size); 086 for(Iterator<SystemProperty> iter = propertyMap.values().iterator();iter.hasNext();){ 087 SystemProperty property = iter.next(); 088 String propertyFilePath = property.getPropertyFilePath(); 089 if(propertyFilePath != null && !propertyFilePath.equals(SystemProperty.SYSTEM_PROPERTY_FILE)){ // check if custom property file location has been given 090 LOGGER.debug("Found property with custom file path."); 091 Properties customProperties = new Properties(); 092 try (InputStream customStream = classLoader.getResourceAsStream(propertyFilePath)) { 093 if(customStream == null){ 094 throw new IllegalArgumentException("Failed to load custom property file: "+propertyFilePath+", for "+property.getClass().toString()); 095 } 096 customProperties.load(customStream); 097 property.initialize(customProperties); 098 } 099 }else{ 100 property.initialize(systemProperties); 101 } 102 _properties.put(property.getClass(), property); 103 // String confi 104 } 105 } catch (IOException ex) { 106 LOGGER.error(ex, ex); 107 throw new IllegalArgumentException("Failed to read property file."); 108 } 109 } 110 111 /** 112 * Get the defined URL e.g. https://example.org/context/ 113 * @return bind context of the service 114 */ 115 public String getBindContext() { 116 return _bindContext; 117 } 118 119 /** 120 * Get the defined URL e.g. https://example.org/context/rest/ 121 * @return REST bind context of the service 122 */ 123 public String getRESTBindContext() { 124 return _restBindContext; 125 } 126 127 /** 128 * Do NOT close or cleanup the instances returned by this method, the initialization and destruction is handled automatically. 129 * 130 * @param cls 131 * @return system properties of the given class or null if not found 132 */ 133 @SuppressWarnings("unchecked") 134 public <T extends SystemProperty> T getSystemProperties(Class<T> cls) { 135 return (T) (_properties == null ? null : _properties.get(cls)); 136 } 137 138 /** 139 * close this handler and release all resources 140 */ 141 public void close(){ 142 _bindContext = null; 143 _restBindContext = null; 144 _properties = null; 145 _context.close(); 146 _context = null; 147 } 148}