View Javadoc
1   package fr.ifremer.quadrige2.synchro.server.config;
2   
3   /*-
4    * #%L
5    * Quadrige2 Core :: Quadrige2 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.quadrige2.core.config.Quadrige2Configuration;
30  import fr.ifremer.quadrige2.core.config.Quadrige2ConfigurationOption;
31  import fr.ifremer.quadrige2.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 Quadrige2Configuration {
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.quadrige2.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                 Quadrige2ConfigurationOption.JDBC_URL.getKey(),
137                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_URL.getKey()));
138         // Override JDBC_CATALOG option to propagate default value
139 //        if (applicationConfig.hasOption(SynchroServerConfigurationOption.SERVER_JDBC_CATALOG)) {
140             applicationConfig.setDefaultOption(
141                     Quadrige2ConfigurationOption.JDBC_CATALOG.getKey(),
142                     String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_CATALOG.getKey()));
143 //        }
144         applicationConfig.setDefaultOption(
145                 Quadrige2ConfigurationOption.JDBC_SCHEMA.getKey(),
146                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_SCHEMA.getKey()));
147         applicationConfig.setDefaultOption(
148                 Quadrige2ConfigurationOption.JDBC_USERNAME.getKey(),
149                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_USERNAME.getKey()));
150         applicationConfig.setDefaultOption(
151                 Quadrige2ConfigurationOption.JDBC_PASSWORD.getKey(),
152                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_PASSWORD.getKey()));
153         applicationConfig.setDefaultOption(
154                 Quadrige2ConfigurationOption.HIBERNATE_DIALECT.getKey(),
155                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_HIBERNATE_DIALECT.getKey()));
156         applicationConfig.setDefaultOption(
157                 Quadrige2ConfigurationOption.JDBC_DRIVER.getKey(),
158                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_DRIVER.getKey()));
159 
160         // Override synchro DB name, with
161         applicationConfig.setDefaultOption(
162                 SynchroConfigurationOption.DB_NAME.getKey(),
163                 String.format("${%s}", Quadrige2ConfigurationOption.DB_NAME.getKey()));
164 
165         // Override synchro database properties (source = server DB)
166         applicationConfig.setDefaultOption(
167                 SynchroConfigurationOption.IMPORT_JDBC_URL.getKey(),
168                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_URL.getKey()));
169         // Override JDBC_CATALOG option to propagate default value
170 //        if (applicationConfig.hasOption(SynchroServerConfigurationOption.SERVER_JDBC_CATALOG)) {
171             applicationConfig.setDefaultOption(
172                     SynchroConfigurationOption.IMPORT_JDBC_CATALOG.getKey(),
173                     String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_CATALOG.getKey()));
174 //        }
175         applicationConfig.setDefaultOption(
176                 SynchroConfigurationOption.IMPORT_JDBC_SCHEMA.getKey(),
177                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_SCHEMA.getKey()));
178         applicationConfig.setDefaultOption(
179                 SynchroConfigurationOption.IMPORT_JDBC_USERNAME.getKey(),
180                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_USERNAME.getKey()));
181         applicationConfig.setDefaultOption(
182                 SynchroConfigurationOption.IMPORT_JDBC_PASSWORD.getKey(),
183                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_PASSWORD.getKey()));
184         applicationConfig.setDefaultOption(
185                 SynchroConfigurationOption.IMPORT_HIBERNATE_DIALECT.getKey(),
186                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_HIBERNATE_DIALECT.getKey()));
187         applicationConfig.setDefaultOption(
188                 SynchroConfigurationOption.IMPORT_JDBC_DRIVER.getKey(),
189                 String.format("${%s}", SynchroServerConfigurationOption.SERVER_JDBC_DRIVER.getKey()));
190 
191         // Override synchro database properties (target = client DB)
192         applicationConfig.setDefaultOption(
193                 SynchroConfigurationOption.JDBC_URL.getKey(),
194                 String.format("${%s}", SynchroServerConfigurationOption.CLIENT_JDBC_URL.getKey()));
195         applicationConfig.setDefaultOption(
196                 SynchroConfigurationOption.JDBC_CATALOG.getKey(),
197                 SynchroServerConfigurationOption.CLIENT_JDBC_CATALOG.getDefaultValue());
198         applicationConfig.setDefaultOption(
199                 SynchroConfigurationOption.JDBC_SCHEMA.getKey(),
200                 String.format("${%s}", SynchroServerConfigurationOption.CLIENT_JDBC_SCHEMA.getKey()));
201         applicationConfig.setDefaultOption(
202                 SynchroConfigurationOption.JDBC_USERNAME.getKey(),
203                 String.format("${%s}", SynchroServerConfigurationOption.CLIENT_JDBC_USERNAME.getKey()));
204         applicationConfig.setDefaultOption(
205                 SynchroConfigurationOption.JDBC_PASSWORD.getKey(),
206                 SynchroServerConfigurationOption.CLIENT_JDBC_PASSWORD.getDefaultValue());
207         applicationConfig.setDefaultOption(
208                 SynchroConfigurationOption.HIBERNATE_DIALECT.getKey(),
209                 String.format("${%s}", SynchroServerConfigurationOption.CLIENT_HIBERNATE_DIALECT.getKey()));
210         applicationConfig.setDefaultOption(
211                 SynchroConfigurationOption.JDBC_DRIVER.getKey(),
212                 String.format("${%s}", SynchroServerConfigurationOption.CLIENT_JDBC_DRIVER.getKey()));
213 
214         // Override synchro DB timezone
215         applicationConfig.setDefaultOption(
216                 SynchroConfigurationOption.DB_TIMEZONE.getKey(),
217                 String.format("${%s}", Quadrige2ConfigurationOption.DB_TIMEZONE.getKey()));
218     }
219 
220 
221     /**
222      * <p>getVersionAsString.</p>
223      *
224      * @return a {@link java.lang.String} object.
225      */
226     public String getVersionAsString() {
227         return getVersion().toString();
228     }
229     
230     /**
231      * <p>getMinCompatibleVersion.</p>
232      *
233      * @return a {@link org.nuiton.version.Version} object.
234      */
235     public Version getMinCompatibleVersion() {
236         // If config option is an empty empty, make sure to return null (see mantis #25340)
237         String versionAsString = applicationConfig.getOption(SynchroServerConfigurationOption.SYNCHRO_MIN_COMPATIBLE_VERSION.getKey());
238         if (StringUtils.isNotBlank(versionAsString)) {
239             return VersionBuilder.create(versionAsString).build();
240         }
241         return null;
242     }
243 
244     /**
245      * <p>getSynchroCorePoolSize.</p>
246      *
247      * @return a int.
248      */
249     public int getSynchroCorePoolSize() {
250         return applicationConfig.getOptionAsInt(SynchroServerConfigurationOption.SYNCHRO_CORE_POOL_SIZE.getKey());
251     }
252 
253     /**
254      * <p>getSynchroMaxPoolSize.</p>
255      *
256      * @return a int.
257      */
258     public int getSynchroMaxPoolSize() {
259         return applicationConfig.getOptionAsInt(SynchroServerConfigurationOption.SYNCHRO_MAX_POOL_SIZE.getKey());
260     }
261 
262     /**
263      * <p>getSynchroQueueCapacity.</p>
264      *
265      * @return a int.
266      */
267     public int getSynchroQueueCapacity() {
268         return applicationConfig.getOptionAsInt(SynchroServerConfigurationOption.SYNCHRO_QUEUE_CAPACITY.getKey());
269     }
270     
271     /**
272      * <p>getSecurityMockUsername.</p>
273      *
274      * @return a {@link java.lang.String} object.
275      */
276     public String getSecurityMockUsername() {
277         return applicationConfig.getOption(SynchroServerConfigurationOption.SECURITY_MOCK_USERNAME.getKey());
278     }
279     
280     /**
281      * <p>getSecurityMockPassword.</p>
282      *
283      * @return a {@link java.lang.String} object.
284      */
285     public String getSecurityMockPassword() {
286         return applicationConfig.getOption(SynchroServerConfigurationOption.SECURITY_MOCK_PASSWORD.getKey());
287     }
288 
289     /**
290      * <p>getSecurityMockUserId.</p>
291      *
292      * @return a int.
293      */
294     public int getSecurityMockUserId() {
295         return applicationConfig.getOptionAsInt(SynchroServerConfigurationOption.SECURITY_MOCK_USER_ID.getKey());
296     }
297     
298     /**
299      * Time of job status retention, after the end of a job (import or export) - in seconds
300      *
301      * @return a int.
302      */
303     public int getSynchroStatusIdleTimeSeconds() {
304         return applicationConfig.getOptionAsInt(SynchroServerConfigurationOption.SYNCHRO_STATUS_TIME_TO_IDLE.getKey());
305     }
306 
307     /**
308      * <p>getUiBaseURL.</p>
309      *
310      * @return a {@link java.net.URL} object.
311      */
312     public URL getUiBaseURL() {
313         return applicationConfig.getOptionAsURL(SynchroServerConfigurationOption.UI_BASE_URL.getKey());
314     }
315 
316     /**
317      * <p>isSynchroServiceLazy.</p>
318      *
319      * @return a boolean.
320      */
321     public boolean isSynchroServiceLazy() {
322         return applicationConfig.getOptionAsBoolean(SynchroServerConfigurationOption.SYNCHRO_SERVICE_LAZY.getKey());
323     }
324 
325     public String getSynchroExportFinalizeProcedures() {
326         return applicationConfig.getOption(SynchroServerConfigurationOption.SYNCHRO_EXPORT_FINALIZE_PROCEDURES.getKey());
327     }
328 
329     /**
330      * <p>getUploadDirectoryByUser.</p>
331      *
332      * @param userId a int.
333      * @return a {@link java.io.File} object.
334      */
335     public File getUploadDirectoryByUser(int userId) {
336         File uploadDir = new File(
337             getTempDirectory(),
338             String.valueOf(userId));
339         return uploadDir;
340     }
341 
342     /**
343      * <p>getClientConnectionProperties.</p>
344      *
345      * @return a {@link java.util.Properties} object.
346      */
347     public Properties getClientConnectionProperties() {
348         return Daos.getConnectionProperties(
349                 getClientJdbcURL(),
350                 getClientJdbcUsername(),
351                 getClientJdbcPassword(),
352                 null,
353                 getClientHibernateDialect(),
354                 getClientJdbcDriver());
355     }
356 
357     /**
358      * <p>getClientHibernateDialect.</p>
359      *
360      * @return a {@link java.lang.String} object.
361      */
362     public String getClientHibernateDialect() {
363         return applicationConfig.getOption(SynchroServerConfigurationOption.CLIENT_HIBERNATE_DIALECT.getKey());
364     }
365 
366     /**
367      * <p>getClientJdbcDriver.</p>
368      *
369      * @return a {@link java.lang.String} object.
370      */
371     public String getClientJdbcDriver() {
372         return applicationConfig.getOption(SynchroServerConfigurationOption.CLIENT_JDBC_DRIVER.getKey());
373     }
374 
375     /**
376      * <p>getClientJdbcURL.</p>
377      *
378      * @return a {@link java.lang.String} object.
379      */
380     public String getClientJdbcURL() {
381         return applicationConfig.getOption(SynchroServerConfigurationOption.CLIENT_JDBC_URL.getKey());
382     }
383 
384     /**
385      * <p>getClientJdbcCatalog.</p>
386      *
387      * @return a {@link java.lang.String} object.
388      */
389     public String getClientJdbcCatalog() {
390         return applicationConfig.getOption(SynchroServerConfigurationOption.CLIENT_JDBC_CATALOG.getKey());
391     }
392 
393     /**
394      * <p>getClientJdbcSchema.</p>
395      *
396      * @return a {@link java.lang.String} object.
397      */
398     public String getClientJdbcSchema() {
399         return applicationConfig.getOption(SynchroServerConfigurationOption.CLIENT_JDBC_SCHEMA.getKey());
400     }
401 
402     /**
403      * <p>getClientJdbcUsername.</p>
404      *
405      * @return a {@link java.lang.String} object.
406      */
407     public String getClientJdbcUsername() {
408         return applicationConfig.getOption(SynchroServerConfigurationOption.CLIENT_JDBC_USERNAME.getKey());
409     }
410 
411     /**
412      * <p>getClientJdbcPassword.</p>
413      *
414      * @return a {@link java.lang.String} object.
415      */
416     public String getClientJdbcPassword() {
417         return applicationConfig.getOption(SynchroServerConfigurationOption.CLIENT_JDBC_PASSWORD.getKey());
418     }
419 
420 
421     /* -- Internal methods -- */
422 
423     /**
424      * <p>getWebConfigFile.</p>
425      *
426      * @return a {@link java.lang.String} object.
427      */
428     protected static String getWebConfigFile() {
429         // Could override config file name (useful for dev)
430         String configFile = CONFIG_FILE_NAME;
431         if (System.getProperty(CONFIG_FILE_ENV_PROPERTY) != null) {
432             configFile = System.getProperty(CONFIG_FILE_ENV_PROPERTY);
433             configFile = configFile.replaceAll("\\\\", "/");
434         }
435         else {
436             try {
437                 InitialContext ic = new InitialContext();
438                 String jndiPathToConfFile = (String) ic.lookup(CONFIG_FILE_JNDI_NAME);
439                 if (StringUtils.isNotBlank(jndiPathToConfFile)) {
440                     configFile = jndiPathToConfFile;
441                 }
442             } catch (NamingException e) {
443                 log.warn(String.format("Error while reading JNDI initial context. Skip configuration path override, from context [%s]", CONFIG_FILE_JNDI_NAME));
444             }
445         }
446 
447         return configFile;
448     }
449 
450     /**
451      * <p>initI18n.</p>
452      *
453      * @throws java.io.IOException if any.
454      */
455     protected void initI18n() throws IOException {
456 
457         // --------------------------------------------------------------------//
458         // init i18n
459         // --------------------------------------------------------------------//
460         File i18nDirectory = new File(getDataDirectory(), "i18n");
461         if (i18nDirectory.exists()) {
462             // clean i18n cache
463             FileUtils.cleanDirectory(i18nDirectory);
464         }
465 
466         FileUtils.forceMkdir(i18nDirectory);
467 
468         if (log.isDebugEnabled()) {
469             log.debug("I18N directory: " + i18nDirectory);
470         }
471 
472         Locale i18nLocale = getI18nLocale();
473 
474         if (log.isInfoEnabled()) {
475             log.info(I18n.t("quadrige2.synchro.server.init.i18n",
476                     i18nLocale, i18nDirectory));
477         }
478         I18n.init(new UserI18nInitializer(
479             i18nDirectory, new DefaultI18nInitializer(getI18nBundleName())),
480             i18nLocale);
481     }
482 
483     /**
484      * <p>initDirectories.</p>
485      *
486      * @throws java.io.IOException if any.
487      */
488     protected void initDirectories() throws IOException {
489 
490         // log the data directory used
491         log.info(I18n.t("quadrige2.synchro.server.init.data.directory", getDataDirectory()));
492 
493         // Synchro directory
494         FileUtils.forceMkdir(getSynchronizationDirectory());
495 
496         // cache directory
497         FileUtils.forceMkdir(getCacheDirectory());
498 
499         // temp directory 
500         File tempDirectory = getTempDirectory();
501         if (tempDirectory.exists()) {
502             // clean temp files
503             FileUtils.cleanDirectory(tempDirectory);
504         }
505     }
506 
507     /**
508      * <p>getI18nBundleName.</p>
509      *
510      * @return a {@link java.lang.String} object.
511      */
512     protected static String getI18nBundleName() {
513         return "quadrige2-synchro-server-i18n";
514     }
515 
516     /**
517      * Initialization default timezone, from configuration (mantis #34754)
518      */
519     @Override
520     protected void initTimeZone() {
521 
522         String timeZone = applicationConfig.getOption(SynchroServerConfigurationOption.TIMEZONE.getKey());
523         if (StringUtils.isNotBlank(timeZone)) {
524             log.info(String.format("Using timezone [%s]", timeZone));
525             TimeZone.setDefault(TimeZone.getTimeZone(timeZone));
526             System.setProperty("user.timezone", timeZone);
527         } else {
528             log.info(String.format("Using default timezone [%s]", System.getProperty("user.timezone")));
529         }
530 
531         String dbTimeZone = applicationConfig.getOption(Quadrige2ConfigurationOption.DB_TIMEZONE.getKey());
532         if (StringUtils.isNotBlank(dbTimeZone)) {
533             log.info(String.format("Using timezone [%s] for database", dbTimeZone));
534         } else {
535             log.info(String.format("Using default timezone [%s] for database", System.getProperty("user.timezone")));
536         }
537     }
538 
539 }