View Javadoc
1   package fr.ifremer.quadrige3.synchro.server.config;
2   
3   /*-
4    * #%L
5    * Quadrige3 Core :: Quadrige3 Synchro server
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2017 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU Affero General Public License as published by
13   * the Free Software Foundation, either version 3 of the License, or
14   * (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU Affero General Public License
22   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23   * #L%
24   */
25  
26  import fr.ifremer.common.synchro.SynchroTechnicalException;
27  import fr.ifremer.common.synchro.config.SynchroConfiguration;
28  import fr.ifremer.common.synchro.config.SynchroConfigurationOption;
29  import fr.ifremer.quadrige3.core.config.QuadrigeConfiguration;
30  import fr.ifremer.quadrige3.core.config.QuadrigeConfigurationOption;
31  import fr.ifremer.quadrige3.core.dao.technical.Daos;
32  import org.apache.commons.io.FileUtils;
33  import org.apache.commons.lang3.StringUtils;
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  import org.nuiton.config.ApplicationConfig;
37  import org.nuiton.i18n.I18n;
38  import org.nuiton.i18n.init.DefaultI18nInitializer;
39  import org.nuiton.i18n.init.UserI18nInitializer;
40  import org.nuiton.version.Version;
41  import org.nuiton.version.VersionBuilder;
42  
43  import javax.naming.InitialContext;
44  import javax.naming.NamingException;
45  import java.io.File;
46  import java.io.IOException;
47  import java.net.URL;
48  import java.util.Locale;
49  import java.util.Properties;
50  import java.util.TimeZone;
51  
52  /**
53   * <p>SynchroServerConfiguration class.</p>
54   *
55   */
56  public class SynchroServerConfiguration extends QuadrigeConfiguration {
57      
58      public static final String CONFIG_FILE_NAME = "synchro-server.config";
59      
60      private static final String CONFIG_FILE_ENV_PROPERTY = CONFIG_FILE_NAME;
61      
62      private static final String CONFIG_FILE_JNDI_NAME = "java:comp/env/" + CONFIG_FILE_NAME;
63      
64      
65      /* Logger */
66      private static final Log log = LogFactory.getLog(SynchroServerConfiguration.class);
67  
68      static {
69          instance = new SynchroServerConfiguration(getWebConfigFile());
70          initDefault();
71      }
72  
73      private static final SynchroServerConfiguration instance;
74  
75      /**
76       * <p>initDefault.</p>
77       */
78      public static void initDefault() {
79          setInstance(instance);
80  
81          // Cascade the application config to the synchro module
82          SynchroConfiguration synchroConfig = new SynchroConfiguration(instance.getApplicationConfig());
83          SynchroConfiguration.setInstance(synchroConfig);
84      }
85  
86      /**
87       * <p>Getter for the field <code>instance</code>.</p>
88       *
89       * @return a {@link fr.ifremer.quadrige3.synchro.server.config.SynchroServerConfiguration} object.
90       */
91      public static SynchroServerConfiguration getInstance() {
92          return instance;
93      }
94  
95      /**
96       * <p>Constructor for SynchroServerConfiguration.</p>
97       *
98       * @param applicationConfig a {@link org.nuiton.config.ApplicationConfig} object.
99       */
100     public SynchroServerConfiguration(ApplicationConfig applicationConfig) {
101         super(applicationConfig);
102     }
103 
104     /**
105      * <p>Constructor for SynchroServerConfiguration.</p>
106      *
107      * @param file a {@link java.lang.String} object.
108      * @param args a {@link java.lang.String} object.
109      */
110     public SynchroServerConfiguration(String file, String... args) {
111         super(file, args);
112 
113         // Init i18n
114         try {
115             initI18n();
116         } catch (IOException e) {
117             throw new SynchroTechnicalException("i18n initialization failed", e);
118         }
119 
120         // Init directories
121         try {
122             initDirectories();
123         } catch (IOException e) {
124             throw new SynchroTechnicalException("Directories initialization failed", e);
125         }
126 
127     }
128 
129     /** {@inheritDoc} */
130     @Override
131     protected void overrideExternalModulesDefaultOptions(ApplicationConfig applicationConfig) {
132         super.overrideExternalModulesDefaultOptions(applicationConfig);
133 
134         // Override hibernate properties with server properties
135         applicationConfig.setDefaultOption(
136                 QuadrigeConfigurationOption.DBMS.getKey(),
137                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_DATASOURCE_TYPE.getKey()));
138         applicationConfig.setDefaultOption(
139                 QuadrigeConfigurationOption.JDBC_URL.getKey(),
140                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_URL.getKey()));
141         // Override JDBC_CATALOG option to propagate default value
142 //        if (applicationConfig.hasOption(SynchroServerConfigurationOption.SERVER_JDBC_CATALOG)) {
143             applicationConfig.setDefaultOption(
144                     QuadrigeConfigurationOption.JDBC_CATALOG.getKey(),
145                     String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_CATALOG.getKey()));
146 //        }
147         applicationConfig.setDefaultOption(
148                 QuadrigeConfigurationOption.JDBC_SCHEMA.getKey(),
149                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_SCHEMA.getKey()));
150         applicationConfig.setDefaultOption(
151                 QuadrigeConfigurationOption.JDBC_USERNAME.getKey(),
152                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_USERNAME.getKey()));
153         applicationConfig.setDefaultOption(
154                 QuadrigeConfigurationOption.JDBC_PASSWORD.getKey(),
155                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_PASSWORD.getKey()));
156         applicationConfig.setDefaultOption(
157                 QuadrigeConfigurationOption.HIBERNATE_DIALECT.getKey(),
158                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_HIBERNATE_DIALECT.getKey()));
159         applicationConfig.setDefaultOption(
160                 QuadrigeConfigurationOption.JDBC_DRIVER.getKey(),
161                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_DRIVER.getKey()));
162 
163         // Override synchro DB name, with
164         applicationConfig.setDefaultOption(
165                 SynchroConfigurationOption.DB_NAME.getKey(),
166                 String.format("${%s}", QuadrigeConfigurationOption.DB_NAME.getKey()));
167 
168         // Override synchro database properties (source = server DB)
169         applicationConfig.setDefaultOption(
170                 SynchroConfigurationOption.IMPORT_JDBC_URL.getKey(),
171                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_URL.getKey()));
172         // Override JDBC_CATALOG option to propagate default value
173 //        if (applicationConfig.hasOption(SynchroServerConfigurationOption.SERVER_JDBC_CATALOG)) {
174             applicationConfig.setDefaultOption(
175                     SynchroConfigurationOption.IMPORT_JDBC_CATALOG.getKey(),
176                     String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_CATALOG.getKey()));
177 //        }
178         applicationConfig.setDefaultOption(
179                 SynchroConfigurationOption.IMPORT_JDBC_SCHEMA.getKey(),
180                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_SCHEMA.getKey()));
181         applicationConfig.setDefaultOption(
182                 SynchroConfigurationOption.IMPORT_JDBC_USERNAME.getKey(),
183                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_USERNAME.getKey()));
184         applicationConfig.setDefaultOption(
185                 SynchroConfigurationOption.IMPORT_JDBC_PASSWORD.getKey(),
186                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_PASSWORD.getKey()));
187         applicationConfig.setDefaultOption(
188                 SynchroConfigurationOption.IMPORT_HIBERNATE_DIALECT.getKey(),
189                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_HIBERNATE_DIALECT.getKey()));
190         applicationConfig.setDefaultOption(
191                 SynchroConfigurationOption.IMPORT_JDBC_DRIVER.getKey(),
192                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_DRIVER.getKey()));
193 
194         // Override synchro database properties (target = client DB)
195         applicationConfig.setDefaultOption(
196                 SynchroConfigurationOption.JDBC_URL.getKey(),
197                 String.format("${%s}", SynchroServerConfigurationOption.CLIENT_JDBC_URL.getKey()));
198         applicationConfig.setDefaultOption(
199                 SynchroConfigurationOption.JDBC_CATALOG.getKey(),
200                 SynchroServerConfigurationOption.CLIENT_JDBC_CATALOG.getDefaultValue());
201         applicationConfig.setDefaultOption(
202                 SynchroConfigurationOption.JDBC_SCHEMA.getKey(),
203                 String.format("${%s}", SynchroServerConfigurationOption.CLIENT_JDBC_SCHEMA.getKey()));
204         applicationConfig.setDefaultOption(
205                 SynchroConfigurationOption.JDBC_USERNAME.getKey(),
206                 String.format("${%s}", SynchroServerConfigurationOption.CLIENT_JDBC_USERNAME.getKey()));
207         applicationConfig.setDefaultOption(
208                 SynchroConfigurationOption.JDBC_PASSWORD.getKey(),
209                 SynchroServerConfigurationOption.CLIENT_JDBC_PASSWORD.getDefaultValue());
210         applicationConfig.setDefaultOption(
211                 SynchroConfigurationOption.HIBERNATE_DIALECT.getKey(),
212                 String.format("${%s}", SynchroServerConfigurationOption.CLIENT_HIBERNATE_DIALECT.getKey()));
213         applicationConfig.setDefaultOption(
214                 SynchroConfigurationOption.JDBC_DRIVER.getKey(),
215                 String.format("${%s}", SynchroServerConfigurationOption.CLIENT_JDBC_DRIVER.getKey()));
216 
217         // Override synchro DB timezone
218         applicationConfig.setDefaultOption(
219                 SynchroConfigurationOption.DB_TIMEZONE.getKey(),
220                 String.format("${%s}", QuadrigeConfigurationOption.DB_TIMEZONE.getKey()));
221     }
222 
223 
224     /**
225      * <p>getVersionAsString.</p>
226      *
227      * @return a {@link java.lang.String} object.
228      */
229     public String getVersionAsString() {
230         return getVersion().toString();
231     }
232     
233     /**
234      * <p>getMinCompatibleVersion.</p>
235      *
236      * @return a {@link org.nuiton.version.Version} object.
237      */
238     public Version getMinCompatibleVersion() {
239         // If config option is an empty empty, make sure to return null (see mantis #25340)
240         String versionAsString = applicationConfig.getOption(SynchroServerConfigurationOption.SYNCHRO_MIN_COMPATIBLE_VERSION.getKey());
241         if (StringUtils.isNotBlank(versionAsString)) {
242             return VersionBuilder.create(versionAsString).build();
243         }
244         return null;
245     }
246 
247     /**
248      * <p>getSynchroCorePoolSize.</p>
249      *
250      * @return a int.
251      */
252     public int getSynchroCorePoolSize() {
253         return applicationConfig.getOptionAsInt(SynchroServerConfigurationOption.SYNCHRO_CORE_POOL_SIZE.getKey());
254     }
255 
256     /**
257      * <p>getSynchroMaxPoolSize.</p>
258      *
259      * @return a int.
260      */
261     public int getSynchroMaxPoolSize() {
262         return applicationConfig.getOptionAsInt(SynchroServerConfigurationOption.SYNCHRO_MAX_POOL_SIZE.getKey());
263     }
264 
265     /**
266      * <p>getSynchroQueueCapacity.</p>
267      *
268      * @return a int.
269      */
270     public int getSynchroQueueCapacity() {
271         return applicationConfig.getOptionAsInt(SynchroServerConfigurationOption.SYNCHRO_QUEUE_CAPACITY.getKey());
272     }
273     
274     /**
275      * <p>getSecurityMockUsername.</p>
276      *
277      * @return a {@link java.lang.String} object.
278      */
279     public String getSecurityMockUsername() {
280         return applicationConfig.getOption(SynchroServerConfigurationOption.SECURITY_MOCK_USERNAME.getKey());
281     }
282     
283     /**
284      * <p>getSecurityMockPassword.</p>
285      *
286      * @return a {@link java.lang.String} object.
287      */
288     public String getSecurityMockPassword() {
289         return applicationConfig.getOption(SynchroServerConfigurationOption.SECURITY_MOCK_PASSWORD.getKey());
290     }
291 
292     /**
293      * <p>getSecurityMockUserId.</p>
294      *
295      * @return a int.
296      */
297     public int getSecurityMockUserId() {
298         return applicationConfig.getOptionAsInt(SynchroServerConfigurationOption.SECURITY_MOCK_USER_ID.getKey());
299     }
300     
301     /**
302      * Time of job status retention, after the end of a job (import or export) - in seconds
303      *
304      * @return a int.
305      */
306     public int getSynchroStatusIdleTimeSeconds() {
307         return applicationConfig.getOptionAsInt(SynchroServerConfigurationOption.SYNCHRO_STATUS_TIME_TO_IDLE.getKey());
308     }
309 
310     /**
311      * <p>getUiBaseURL.</p>
312      *
313      * @return a {@link java.net.URL} object.
314      */
315     public URL getUiBaseURL() {
316         return applicationConfig.getOptionAsURL(SynchroServerConfigurationOption.UI_BASE_URL.getKey());
317     }
318 
319     /**
320      * <p>isSynchroServiceLazy.</p>
321      *
322      * @return a boolean.
323      */
324     public boolean isSynchroServiceLazy() {
325         return applicationConfig.getOptionAsBoolean(SynchroServerConfigurationOption.SYNCHRO_SERVICE_LAZY.getKey());
326     }
327 
328     public String getSynchroExportFinalizeProcedures() {
329         return applicationConfig.getOption(SynchroServerConfigurationOption.SYNCHRO_EXPORT_FINALIZE_PROCEDURES.getKey());
330     }
331 
332     /**
333      * <p>getUploadDirectoryByUser.</p>
334      *
335      * @param userId a int.
336      * @return a {@link java.io.File} object.
337      */
338     public File getUploadDirectoryByUser(int userId) {
339         return new File(
340             getTempDirectory(),
341             String.valueOf(userId));
342     }
343 
344     /**
345      * <p>getClientConnectionProperties.</p>
346      *
347      * @return a {@link java.util.Properties} object.
348      */
349     public Properties getClientConnectionProperties() {
350         return Daos.getConnectionProperties(
351                 getClientJdbcURL(),
352                 getClientJdbcUsername(),
353                 getClientJdbcPassword(),
354                 null,
355                 getClientHibernateDialect(),
356                 getClientJdbcDriver());
357     }
358 
359     /**
360      * <p>getClientHibernateDialect.</p>
361      *
362      * @return a {@link java.lang.String} object.
363      */
364     public String getClientHibernateDialect() {
365         return applicationConfig.getOption(SynchroServerConfigurationOption.CLIENT_HIBERNATE_DIALECT.getKey());
366     }
367 
368     /**
369      * <p>getClientJdbcDriver.</p>
370      *
371      * @return a {@link java.lang.String} object.
372      */
373     public String getClientJdbcDriver() {
374         return applicationConfig.getOption(SynchroServerConfigurationOption.CLIENT_JDBC_DRIVER.getKey());
375     }
376 
377     /**
378      * <p>getClientJdbcURL.</p>
379      *
380      * @return a {@link java.lang.String} object.
381      */
382     public String getClientJdbcURL() {
383         return applicationConfig.getOption(SynchroServerConfigurationOption.CLIENT_JDBC_URL.getKey());
384     }
385 
386     /**
387      * <p>getClientJdbcCatalog.</p>
388      *
389      * @return a {@link java.lang.String} object.
390      */
391     public String getClientJdbcCatalog() {
392         return applicationConfig.getOption(SynchroServerConfigurationOption.CLIENT_JDBC_CATALOG.getKey());
393     }
394 
395     /**
396      * <p>getClientJdbcSchema.</p>
397      *
398      * @return a {@link java.lang.String} object.
399      */
400     public String getClientJdbcSchema() {
401         return applicationConfig.getOption(SynchroServerConfigurationOption.CLIENT_JDBC_SCHEMA.getKey());
402     }
403 
404     /**
405      * <p>getClientJdbcUsername.</p>
406      *
407      * @return a {@link java.lang.String} object.
408      */
409     public String getClientJdbcUsername() {
410         return applicationConfig.getOption(SynchroServerConfigurationOption.CLIENT_JDBC_USERNAME.getKey());
411     }
412 
413     /**
414      * <p>getClientJdbcPassword.</p>
415      *
416      * @return a {@link java.lang.String} object.
417      */
418     public String getClientJdbcPassword() {
419         return applicationConfig.getOption(SynchroServerConfigurationOption.CLIENT_JDBC_PASSWORD.getKey());
420     }
421 
422 
423     /* -- Internal methods -- */
424 
425     /**
426      * <p>getWebConfigFile.</p>
427      *
428      * @return a {@link java.lang.String} object.
429      */
430     protected static String getWebConfigFile() {
431         // Could override config file name (useful for dev)
432         String configFile = CONFIG_FILE_NAME;
433         if (System.getProperty(CONFIG_FILE_ENV_PROPERTY) != null) {
434             configFile = System.getProperty(CONFIG_FILE_ENV_PROPERTY);
435             configFile = configFile.replaceAll("\\\\", "/");
436         }
437         else {
438             try {
439                 InitialContext ic = new InitialContext();
440                 String jndiPathToConfFile = (String) ic.lookup(CONFIG_FILE_JNDI_NAME);
441                 if (StringUtils.isNotBlank(jndiPathToConfFile)) {
442                     configFile = jndiPathToConfFile;
443                 }
444             } catch (NamingException e) {
445                 log.warn(String.format("Error while reading JNDI initial context. Skip configuration path override, from context [%s]", CONFIG_FILE_JNDI_NAME));
446             }
447         }
448 
449         return configFile;
450     }
451 
452     /**
453      * <p>initI18n.</p>
454      *
455      * @throws java.io.IOException if any.
456      */
457     protected void initI18n() throws IOException {
458 
459         // --------------------------------------------------------------------//
460         // init i18n
461         // --------------------------------------------------------------------//
462         File i18nDirectory = new File(getDataDirectory(), "i18n");
463         if (i18nDirectory.exists()) {
464             // clean i18n cache
465             FileUtils.cleanDirectory(i18nDirectory);
466         }
467 
468         FileUtils.forceMkdir(i18nDirectory);
469 
470         if (log.isDebugEnabled()) {
471             log.debug("I18N directory: " + i18nDirectory);
472         }
473 
474         Locale i18nLocale = getI18nLocale();
475 
476         if (log.isInfoEnabled()) {
477             log.info(I18n.t("quadrige3.synchro.server.init.i18n",
478                     i18nLocale, i18nDirectory));
479         }
480         I18n.init(new UserI18nInitializer(
481             i18nDirectory, new DefaultI18nInitializer(getI18nBundleName())),
482             i18nLocale);
483     }
484 
485     /**
486      * <p>initDirectories.</p>
487      *
488      * @throws java.io.IOException if any.
489      */
490     protected void initDirectories() throws IOException {
491 
492         // log the data directory used
493         log.info(I18n.t("quadrige3.synchro.server.init.data.directory", getDataDirectory()));
494 
495         // Synchro directory
496         FileUtils.forceMkdir(getSynchronizationDirectory());
497 
498         // cache directory
499         FileUtils.forceMkdir(getCacheDirectory());
500 
501         // temp directory 
502         File tempDirectory = getTempDirectory();
503         if (tempDirectory.exists()) {
504             // clean temp files
505             FileUtils.cleanDirectory(tempDirectory);
506         }
507     }
508 
509     /**
510      * <p>getI18nBundleName.</p>
511      *
512      * @return a {@link java.lang.String} object.
513      */
514     protected static String getI18nBundleName() {
515         return "quadrige3-synchro-server-i18n";
516     }
517 
518     /**
519      * Initialization default timezone, from configuration (mantis #34754)
520      */
521     @Override
522     protected void initTimeZone() {
523 
524         String timeZone = applicationConfig.getOption(SynchroServerConfigurationOption.TIMEZONE.getKey());
525         if (StringUtils.isNotBlank(timeZone)) {
526             log.info(String.format("Using timezone [%s]", timeZone));
527             TimeZone.setDefault(TimeZone.getTimeZone(timeZone));
528             System.setProperty("user.timezone", timeZone);
529         } else {
530             log.info(String.format("Using default timezone [%s]", System.getProperty("user.timezone")));
531         }
532 
533         String dbTimeZone = applicationConfig.getOption(QuadrigeConfigurationOption.DB_TIMEZONE.getKey());
534         if (StringUtils.isNotBlank(dbTimeZone)) {
535             log.info(String.format("Using timezone [%s] for database", dbTimeZone));
536         } else {
537             log.info(String.format("Using default timezone [%s] for database", System.getProperty("user.timezone")));
538         }
539     }
540 
541     public void save() throws IOException {
542         applicationConfig.save(new File(getWebConfigFile()), false);
543     }
544 }