1 /*
2 * Copyright (c) 2002-2025, City of Paris
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice
10 * and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice
13 * and the following disclaimer in the documentation and/or other materials
14 * provided with the distribution.
15 *
16 * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *
32 * License 1.0
33 */
34 package fr.paris.lutece.util;
35
36 import java.io.File;
37 import java.io.FileInputStream;
38 import java.io.IOException;
39 import java.security.GeneralSecurityException;
40 import java.util.LinkedHashMap;
41 import java.util.Map;
42 import java.util.Properties;
43
44 import org.apache.commons.lang3.ArrayUtils;
45
46 import fr.paris.lutece.portal.service.security.RsaService;
47 import fr.paris.lutece.portal.service.util.AppLogService;
48 import fr.paris.lutece.portal.service.util.AppPropertiesService;
49
50 /**
51 * This class provides utility methods to read values of the properties stored in the .properties file of the application.
52 */
53 public class PropertiesService
54 {
55 // Static variables
56 private String _strRootPath;
57 private Properties _properties = new Properties( );
58 private Map<String, String> _mapPropertiesFiles = new LinkedHashMap<>( );
59
60 public final String RSA_KEY_PREFIX = "PROTECTED::RSA::";
61 private final String MESSAGE_CIPHERED_PROPERTY_SECURITY_EXCEPTION = "A ciphered property security exception occured." ;
62
63 /**
64 * Constructor should define the base root path for properties files
65 *
66 * @param strRootPath
67 * The root path
68 */
69 public PropertiesService( String strRootPath )
70 {
71 _strRootPath = ( strRootPath.endsWith( "/" ) ) ? strRootPath : ( strRootPath + "/" );
72 }
73
74 /**
75 * Add properties from a properties file
76 *
77 * @param strRelativePath
78 * Relative path from the root path
79 * @param strFilename
80 * The filename of the properties file (ie: config.properties)
81 */
82 public void addPropertiesFile( String strRelativePath, String strFilename )
83 {
84 String strFullPath = _strRootPath + ( ( strRelativePath.endsWith( "/" ) ) ? strRelativePath : ( strRelativePath + "/" ) ) + strFilename;
85 _mapPropertiesFiles.put( strFilename, strFullPath );
86 loadFile( strFullPath );
87 }
88
89 /**
90 * Add properties from all files found in a given directory
91 *
92 * @param strRelativePath
93 * Relative path from the root path
94 */
95 public void addPropertiesDirectory( String strRelativePath )
96 {
97 File directory = new File( _strRootPath + strRelativePath );
98
99 if ( directory.exists( ) )
100 {
101 File [ ] listFile = directory.listFiles( );
102
103 if ( ArrayUtils.isNotEmpty( listFile ) )
104 {
105 for ( File file : listFile )
106 {
107 if ( file.getName( ).endsWith( ".properties" ) )
108 {
109 String strFullPath = file.getAbsolutePath( );
110 _mapPropertiesFiles.put( file.getName( ), strFullPath );
111 loadFile( strFullPath );
112 }
113 }
114 }
115 }
116 }
117
118 /**
119 * Load properties of a file
120 *
121 * @param strFullPath
122 * The absolute path of the properties file
123 */
124 private void loadFile( String strFullPath )
125 {
126 loadFile( strFullPath, _properties );
127 }
128
129 /**
130 * Load properties of a file
131 *
132 * @param strFullPath
133 * The absolute path of the properties file
134 * @param props
135 * properties to load into
136 * @throws java.io.IOException
137 * If an error occurs reading the file
138 */
139 private void loadFile( String strFullPath, Properties props )
140 {
141 try ( FileInputStream fis = new FileInputStream( new File( strFullPath ) ) )
142 {
143 props.load( fis );
144 }
145 catch( IOException ex )
146 {
147 AppLogService.error( "Error loading property file : {}", ex.getMessage( ), ex );
148 }
149 }
150
151 /**
152 * Reload a properties file .
153 *
154 * @param strFilename
155 * The filename of the properties file
156 */
157 public void reload( String strFilename )
158 {
159 String strFullPath = _mapPropertiesFiles.get( strFilename );
160 loadFile( strFullPath );
161 }
162
163 /**
164 * Reload all properties files
165 *
166 */
167 public void reloadAll( )
168 {
169 Properties newProperties = new Properties( );
170
171 for ( String strFullPath : _mapPropertiesFiles.values( ) )
172 {
173 loadFile( strFullPath, newProperties );
174 }
175
176 _properties = newProperties;
177 }
178
179 /**
180 * Returns the value of a variable defined in the .properties file of the application as a String
181 *
182 * @param strProperty
183 * The variable name
184 * @return The variable value read in the properties file
185 */
186 public String getProperty( String strProperty )
187 {
188 String strValue = _properties.getProperty( strProperty ) ;
189
190 if ( strValue != null && strValue.startsWith( RSA_KEY_PREFIX ) )
191 {
192 try
193 {
194 return RsaService.decryptRsa( strValue.substring( RSA_KEY_PREFIX.length( ) ) );
195 }
196 catch ( GeneralSecurityException e )
197 {
198 AppLogService.error( MESSAGE_CIPHERED_PROPERTY_SECURITY_EXCEPTION, e );
199 }
200 }
201
202 return strValue;
203 }
204
205 /**
206 * Returns the value of a variable defined in the .properties file of the application as a String
207 *
208 * @param strProperty
209 * The variable name
210 * @param strDefault
211 * The default value which is returned if no value is found for the variable in the .properties file.
212 * @return The variable value read in the properties file
213 */
214 public String getProperty( String strProperty, String strDefault )
215 {
216 return _properties.getProperty( strProperty, strDefault );
217 }
218
219 /**
220 * Returns the value of a variable defined in the .properties file of the application as an int
221 *
222 * @param strProperty
223 * The variable name
224 * @param nDefault
225 * The default value which is returned if no value is found for the variable in the .properties file, or if the value is not numeric
226 * @return The variable value read in the properties file
227 */
228 public int getPropertyInt( String strProperty, int nDefault )
229 {
230 String strValue = AppPropertiesService.getProperty( strProperty );
231 int nValue = nDefault;
232
233 try
234 {
235 if ( strValue != null )
236 {
237 nValue = Integer.parseInt( strValue );
238 }
239 }
240 catch( NumberFormatException e )
241 {
242 AppLogService.info( e.getMessage( ), e );
243 }
244
245 return nValue;
246 }
247
248 /**
249 * Returns the value of a variable defined in the .properties file of the application as an long
250 *
251 * @param strProperty
252 * The variable name
253 * @param lDefault
254 * The default value which is returned if no value is found for the variable in the le downloadFile .properties. .properties file.
255 * @return The variable value read in the properties file
256 */
257 public long getPropertyLong( String strProperty, long lDefault )
258 {
259 String strValue = AppPropertiesService.getProperty( strProperty );
260 long lValue = lDefault;
261
262 try
263 {
264 if ( strValue != null )
265 {
266 lValue = Long.parseLong( strValue );
267 }
268 }
269 catch( NumberFormatException e )
270 {
271 AppLogService.info( e.getMessage( ), e );
272 }
273
274 return lValue;
275 }
276
277 /**
278 * Returns the value of a variable defined in the .properties file of the application as an boolean
279 *
280 * @param strProperty
281 * The variable name
282 * @param bDefault
283 * The default value which is returned if no value is found for the variable in the le downloadFile .properties. .properties file.
284 * @return The variable value read in the properties file
285 */
286 public boolean getPropertyBoolean( String strProperty, boolean bDefault )
287 {
288 String strValue = AppPropertiesService.getProperty( strProperty );
289 boolean bValue = bDefault;
290
291 if ( strValue != null )
292 {
293 bValue = strValue.equalsIgnoreCase( "true" );
294 }
295
296 return bValue;
297 }
298
299 /**
300 * Gets properties
301 *
302 * @return All properties
303 */
304 public Properties getProperties( )
305 {
306 return _properties;
307 }
308 }