1717import com .cloud .utils .PropertiesUtil ;
1818import java .io .File ;
1919import java .io .IOException ;
20+ import java .util .Properties ;
2021import org .apache .cloudstack .utils .security .KeyStoreUtils ;
2122import org .apache .commons .beanutils .ConvertUtils ;
2223import org .apache .commons .beanutils .converters .IntegerConverter ;
2930 * This class provides a facility to read the agent's properties file and get
3031 * its properties, according to the {@link AgentProperties} properties constants.
3132 *
33+ * Properties are loaded lazily and cached until the cache is cleared (for example, after persisting updates).
3234 */
3335public class AgentPropertiesFileHandler {
3436
3537 protected static Logger LOGGER = LogManager .getLogger (AgentPropertiesFileHandler .class );
3638
39+ // Simple singleton caching - loaded once, cached forever
40+ private static volatile Properties cachedProperties ;
41+
3742 /**
3843 * This method reads the property in the agent.properties file.
44+ * Properties are loaded once and cached for the agent's lifetime.
3945 *
4046 * @param property the property to retrieve.
4147 * @return The value of the property. If the property is not available, the
@@ -45,16 +51,15 @@ public static <T> T getPropertyValue(AgentProperties.Property<T> property) {
4551 T defaultValue = property .getDefaultValue ();
4652 String name = property .getName ();
4753
48- File agentPropertiesFile = PropertiesUtil .findConfigFile (KeyStoreUtils .AGENT_PROPSFILE );
49-
50- if (agentPropertiesFile == null ) {
51- LOGGER .debug ("File [{}] was not found, we will use default defined values. Property [{}]: [{}]." , KeyStoreUtils .AGENT_PROPSFILE , name , defaultValue );
54+ Properties properties = getCachedProperties ();
5255
56+ if (properties == null ) {
57+ LOGGER .debug (String .format ("Properties file was not found or could not be loaded, using default values. Property [%s]: [%s]." , name , defaultValue ));
5358 return defaultValue ;
5459 }
5560
5661 try {
57- String configValue = PropertiesUtil . loadFromFile ( agentPropertiesFile ) .getProperty (name );
62+ String configValue = properties .getProperty (name );
5863 if (StringUtils .isBlank (configValue )) {
5964 LOGGER .debug ("Property [{}] has empty or null value. Using default value [{}]." , name , defaultValue );
6065 return defaultValue ;
@@ -71,11 +76,69 @@ public static <T> T getPropertyValue(AgentProperties.Property<T> property) {
7176 LOGGER .debug ("Property [{}] was altered. Now using the value [{}]." , name , configValue );
7277 return (T )ConvertUtils .convert (configValue , property .getTypeClass ());
7378
74- } catch (IOException ex ) {
79+ } catch (RuntimeException ex ) {
7580 LOGGER .debug ("Failed to get property [{}]. Using default value [{}]." , name , defaultValue , ex );
7681 }
7782
7883 return defaultValue ;
7984 }
8085
86+ /**
87+ * Gets the cached properties, loading them once if not already loaded.
88+ * Agent properties are static configuration that don't change during runtime.
89+ *
90+ * @return cached Properties object or null if file cannot be loaded
91+ */
92+ private static Properties getCachedProperties () {
93+ Properties properties = cachedProperties ;
94+ if (properties == null ) {
95+ synchronized (AgentPropertiesFileHandler .class ) {
96+ properties = cachedProperties ;
97+ if (properties == null ) {
98+ loadProperties ();
99+ properties = cachedProperties ;
100+ }
101+ }
102+ }
103+ return properties ;
104+ }
105+
106+ /**
107+ * Loads properties from file and caches them for the agent's lifetime.
108+ */
109+ private static void loadProperties () {
110+ File agentPropertiesFile = PropertiesUtil .findConfigFile (KeyStoreUtils .AGENT_PROPSFILE );
111+
112+ if (agentPropertiesFile == null ) {
113+ LOGGER .debug ("File [{}] was not found." , KeyStoreUtils .AGENT_PROPSFILE );
114+ return ;
115+ }
116+
117+ try {
118+ Properties newProperties = PropertiesUtil .loadFromFile (agentPropertiesFile );
119+ cachedProperties = newProperties ;
120+
121+ LOGGER .info ("Loaded {} properties from [{}]" , newProperties .size (), agentPropertiesFile .getAbsolutePath ());
122+
123+ } catch (IOException ex ) {
124+ LOGGER .error ("Failed to load properties from file [{}]." , agentPropertiesFile .getAbsolutePath (), ex );
125+ }
126+ }
127+
128+ /**
129+ * Clears the properties cache.
130+ */
131+ public static synchronized void clearCache () {
132+ LOGGER .info ("Clearing agent properties cache" );
133+ cachedProperties = null ;
134+ }
135+
136+ /**
137+ * Returns whether the properties cache is currently loaded.
138+ *
139+ * @return true if properties are cached, false otherwise.
140+ */
141+ public static boolean isCacheLoaded () {
142+ return cachedProperties != null ;
143+ }
81144}
0 commit comments