View Javadoc
1   package fr.ifremer.quadrige2.core.config;
2   
3   /*-
4    * #%L
5    * Quadrige2 Core :: Quadrige2 Client Core
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  import com.google.common.collect.Sets;
26  import fr.ifremer.common.synchro.config.SynchroConfiguration;
27  import fr.ifremer.common.synchro.config.SynchroConfigurationOption;
28  import fr.ifremer.quadrige2.core.dao.technical.Daos;
29  import fr.ifremer.quadrige2.core.security.SecurityContextHelper;
30  import fr.ifremer.quadrige2.synchro.meta.DatabaseColumns;
31  import org.apache.commons.lang3.StringUtils;
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.nuiton.config.ApplicationConfig;
35  import org.nuiton.config.ApplicationConfigHelper;
36  import org.nuiton.config.ApplicationConfigProvider;
37  import org.nuiton.config.ArgumentsParserException;
38  import org.nuiton.jaxx.application.ApplicationConfiguration;
39  import org.nuiton.jaxx.application.ApplicationIOUtil;
40  import org.nuiton.jaxx.application.ApplicationTechnicalException;
41  import org.springframework.beans.factory.InitializingBean;
42  
43  import javax.swing.KeyStroke;
44  import java.awt.Color;
45  import java.io.File;
46  import java.io.IOException;
47  import java.net.MalformedURLException;
48  import java.net.URL;
49  import java.nio.charset.StandardCharsets;
50  import java.util.Locale;
51  import java.util.Properties;
52  import java.util.Set;
53  
54  import static org.nuiton.i18n.I18n.t;
55  
56  /**
57   * @author peck7 on 29/06/2017.
58   */
59  public abstract class Quadrige2CoreConfiguration extends ApplicationConfiguration implements InitializingBean {
60  
61      private static final Log LOG = LogFactory.getLog(Quadrige2CoreConfiguration.class);
62  
63      private static Quadrige2CoreConfiguration instance;
64      protected final Set<String> optionKeyToNotSave = Sets.newHashSet();
65      protected File configFile;
66  
67      public Quadrige2CoreConfiguration(ApplicationConfig applicationConfig) {
68          super(applicationConfig);
69          prepareDirectories();
70      }
71  
72      public Quadrige2CoreConfiguration(String file, String... args) {
73          super(new ApplicationConfig());
74  
75          // Set general encoding
76          applicationConfig.setEncoding(StandardCharsets.UTF_8.name());
77          // Set config file name
78          applicationConfig.setConfigFileName(file);
79  
80          // get all config providers (declaring Java 6 SPI)
81          loadProviders();
82  
83          // Add alias
84          addAlias(applicationConfig);
85  
86          try {
87              applicationConfig.parse(args);
88  
89          } catch (ArgumentsParserException e) {
90              throw new ApplicationTechnicalException(t("quadrige2.config.parse.error"), e);
91          }
92  
93          // Override some external module default config (quadrige2)
94          overrideExternalModulesDefaultOptions();
95  
96          // Give the same applicationConfig to quadrige2
97          Quadrige2Configuration quadrige2Config = new Quadrige2Configuration(applicationConfig);
98          Quadrige2Configuration.setInstance(quadrige2Config);
99  
100         // Give the same applicationConfig to synchro
101         SynchroConfiguration synchroConfig = new SynchroConfiguration(applicationConfig);
102         SynchroConfiguration.setInstance(synchroConfig);
103 
104     }
105 
106     private void loadProviders() {
107 
108         // get all config providers (declaring Java 6 SPI)
109         Set<ApplicationConfigProvider> providers = ApplicationConfigHelper.getProviders(null, null, null, true);
110 
111         // load all default options
112         ApplicationConfigHelper.loadAllDefaultOption(applicationConfig, providers);
113 
114         // Load actions
115         for (ApplicationConfigProvider provider : providers) {
116             applicationConfig.loadActions(provider.getActions());
117         }
118 
119         // get all transient and final option keys
120         Set<String> optionToSkip = ApplicationConfigHelper.getTransientOptionKeys(providers);
121 
122         if (LOG.isDebugEnabled()) {
123             LOG.debug("Option that won't be saved: " + optionToSkip);
124         }
125         optionKeyToNotSave.addAll(optionToSkip);
126 
127     }
128 
129     public static Quadrige2CoreConfiguration getInstance() {
130         return instance;
131     }
132 
133     public static void setInstance(Quadrige2CoreConfiguration instance) {
134         Quadrige2CoreConfiguration.instance = instance;
135     }
136 
137     protected void overrideExternalModulesDefaultOptions() {
138 
139         // Map synchro.persistence.XXX to quadrige2.persistence.XXX
140         Quadrige2Configurations.remapOptionsToPrefix(applicationConfig,
141                 "synchro.persistence",
142                 Quadrige2ConfigurationOption.values(),
143                 "quadrige2.persistence");
144 
145         // Map synchro.XXX to quadrige2.synchro.XXX
146         Quadrige2Configurations.remapOptionsToPrefix(applicationConfig,
147                 "synchro",
148                 Quadrige2ConfigurationOption.values(),
149                 "quadrige2.synchro");
150 
151         applicationConfig.setDefaultOption(SynchroConfigurationOption.TEMP_QUERY_PARAMETER_USER_ID.getKey(),
152                 DatabaseColumns.QUSER_ID.name());
153     }
154 
155     /**
156      * Add alias to the given ApplicationConfig. <p/>
157      * This method could be override to add specific alias
158      *
159      * @param applicationConfig a {@link org.nuiton.config.ApplicationConfig} object.
160      */
161     protected void addAlias(ApplicationConfig applicationConfig) {
162         applicationConfig.addAlias("-db", "--option", Quadrige2ConfigurationOption.JDBC_URL.getKey());
163         applicationConfig.addAlias("--database", "--option", Quadrige2ConfigurationOption.JDBC_URL.getKey());
164         applicationConfig.addAlias("--output", "--option", Quadrige2ConfigurationOption.LIQUIBASE_OUTPUT_FILE.getKey());
165 
166     }
167 
168     @Override
169     public KeyStroke getShortcutClosePopup() {
170         return null;
171     }
172 
173     @Override
174     public void afterPropertiesSet() throws Exception {
175         prepareDirectories();
176     }
177 
178     public void prepareDirectories() {
179 
180         File directory = getDataDirectory();
181         ApplicationIOUtil.forceMkdir(directory, t("quadrige2.error.create.directory", directory));
182 
183         directory = getDbDirectory();
184         ApplicationIOUtil.forceMkdir(directory, t("quadrige2.error.create.directory", directory));
185 
186         directory = getDbAttachmentDirectory();
187         ApplicationIOUtil.forceMkdir(directory, t("quadrige2.error.create.directory", directory));
188 
189         directory = getDbBackupDirectory();
190         ApplicationIOUtil.forceMkdir(directory, t("quadrige2.error.create.directory", directory));
191 
192         directory = getPluginsDirectory();
193         ApplicationIOUtil.forceMkdir(directory, t("quadrige2.error.create.directory", directory));
194 
195         directory = getConfigDirectory();
196         ApplicationIOUtil.forceMkdir(directory, t("quadrige2.error.create.directory", directory));
197 
198         directory = getTempDirectory();
199         if (directory.exists()) {
200             ApplicationIOUtil.deleteDirectory(directory, t("quadrige2.error.delete.directory", directory));
201             try {
202                 Thread.sleep(200);
203             } catch (InterruptedException ex) {
204                 LOG.error(ex.getMessage());
205             }
206         }
207         ApplicationIOUtil.forceMkdir(directory, t("quadrige2.error.create.directory", directory));
208 
209     }
210 
211     /*
212      * Database
213      */
214     public File getBaseDirectory() {
215         return applicationConfig.getOptionAsFile(Quadrige2ConfigurationOption.BASEDIR.getKey());
216     }
217 
218     public File getLockFile() {
219         return new File(getBaseDirectory(), "application.lock");
220     }
221 
222     public File getDataDirectory() {
223         return applicationConfig.getOptionAsFile(Quadrige2ConfigurationOption.DATA_DIRECTORY.getKey());
224     }
225 
226     public File getDbDirectory() {
227         return applicationConfig.getOptionAsFile(Quadrige2ConfigurationOption.DB_DIRECTORY.getKey());
228     }
229 
230     public String getDbName() {
231         return applicationConfig.getOption(Quadrige2ConfigurationOption.DB_NAME.getKey());
232     }
233 
234     public String getDbValidationQuery() {
235         return applicationConfig.getOption(Quadrige2ConfigurationOption.DB_VALIDATION_QUERY.getKey());
236     }
237 
238     public File getDbAttachmentDirectory() {
239         return applicationConfig.getOptionAsFile(Quadrige2ConfigurationOption.DB_ATTACHMENT_DIRECTORY.getKey());
240     }
241 
242     public File getDbBackupDirectory() {
243         return applicationConfig.getOptionAsFile(Quadrige2ConfigurationOption.DB_BACKUP_DIRECTORY.getKey());
244     }
245 
246     public File getCacheDirectory() {
247         return applicationConfig.getOptionAsFile(Quadrige2ConfigurationOption.DB_CACHE_DIRECTORY.getKey());
248     }
249 
250     public File getI18nDirectory() {
251         return applicationConfig.getOptionAsFile(Quadrige2ConfigurationOption.I18N_DIRECTORY.getKey());
252     }
253 
254     public File getPluginsDirectory() {
255         return applicationConfig.getOptionAsFile(Quadrige2CoreConfigurationOption.PLUGINS_DIRECTORY.getKey());
256     }
257 
258     public File getConfigDirectory() {
259         return applicationConfig.getOptionAsFile(Quadrige2CoreConfigurationOption.CONFIG_DIRECTORY.getKey());
260     }
261 
262     public File getTempDirectory() {
263         return applicationConfig.getOptionAsFile(Quadrige2ConfigurationOption.TMP_DIRECTORY.getKey());
264     }
265 
266     public String getJdbcUrl() {
267         return applicationConfig.getOption(Quadrige2ConfigurationOption.JDBC_URL.getKey());
268     }
269 
270     public Class<?> getJdbcDriver() {
271         return applicationConfig.getOptionAsClass(Quadrige2ConfigurationOption.JDBC_DRIVER.getKey());
272     }
273 
274     public String getJdbcUsername() {
275         return applicationConfig.getOption(Quadrige2ConfigurationOption.JDBC_USERNAME.getKey());
276     }
277 
278     public String getJdbcPassword() {
279         return applicationConfig.getOption(Quadrige2ConfigurationOption.JDBC_PASSWORD.getKey());
280     }
281 
282     public Class<?> getHibernateDialect() {
283         return applicationConfig.getOptionAsClass(Quadrige2ConfigurationOption.HIBERNATE_DIALECT.getKey());
284     }
285 
286     public boolean isHibernateShowSql() {
287         return applicationConfig.getOptionAsBoolean(Quadrige2ConfigurationOption.HIBERNATE_SHOW_SQL.getKey());
288     }
289 
290     public boolean isHibernateUseSqlComment() {
291         return applicationConfig.getOptionAsBoolean(Quadrige2ConfigurationOption.HIBERNATE_USE_SQL_COMMENT.getKey());
292     }
293 
294     public boolean isHibernateFormatSql() {
295         return applicationConfig.getOptionAsBoolean(Quadrige2ConfigurationOption.HIBERNATE_FORMAT_SQL.getKey());
296     }
297 
298     public Properties getConnectionProperties() {
299         return Daos.getConnectionProperties(
300                 getJdbcUrl(),
301                 getJdbcUsername(),
302                 getJdbcPassword(),
303                 null,
304                 getHibernateDialect().getName(),
305                 getJdbcDriver().getName());
306     }
307 
308     public boolean isDbExists() {
309         if (!Daos.isFileDatabase(getJdbcUrl())) {
310             return true;
311         }
312         File f = new File(getDbDirectory(), getDbName() + ".script");
313         return f.exists();
314     }
315 
316     /*
317      * Update Urls
318      */
319 
320     public String getUpdateApplicationUrl() {
321         return applicationConfig.getOption(Quadrige2CoreConfigurationOption.UPDATE_APPLICATION_URL.getKey());
322     }
323 
324     public String getUpdateDataUrl() {
325         return applicationConfig.getOption(Quadrige2CoreConfigurationOption.UPDATE_DATA_URL.getKey());
326     }
327 
328     public String getInstallDbUrl() {
329         return applicationConfig.getOption(Quadrige2CoreConfigurationOption.INSTALL_DB_URL.getKey());
330     }
331 
332     public String getUpdatePluginsUrl() {
333         return applicationConfig.getOption(Quadrige2CoreConfigurationOption.UPDATE_PLUGINS_URL.getKey());
334     }
335 
336 
337     /*
338      * Authentication 
339      */
340 
341     public boolean isAuthenticationDisabled() {
342         return applicationConfig.getOptionAsBoolean(Quadrige2CoreConfigurationOption.AUTHENTICATION_DISABLED.getKey());
343     }
344 
345     public boolean isAuthenticationForced() {
346         return applicationConfig.getOptionAsBoolean(Quadrige2CoreConfigurationOption.AUTHENTICATION_FORCED.getKey());
347     }
348 
349     public URL getAuthenticationIntranetSiteUrl() {
350         return applicationConfig.getOptionAsURL(Quadrige2CoreConfigurationOption.AUTHENTICATION_INTRANET_SITE_URL.getKey());
351     }
352 
353     public Integer getAuthenticationIntranetSiteTimeout() {
354         return applicationConfig.getOptionAsInt(Quadrige2CoreConfigurationOption.AUTHENTICATION_INTRANET_SITE_TIMEOUT.getKey());
355     }
356 
357     public URL getAuthenticationExtranetSiteUrl() {
358         return applicationConfig.getOptionAsURL(Quadrige2CoreConfigurationOption.AUTHENTICATION_EXTRANET_SITE_URL.getKey());
359     }
360 
361     public Integer getAuthenticationExtranetSiteTimeout() {
362         return applicationConfig.getOptionAsInt(Quadrige2CoreConfigurationOption.AUTHENTICATION_EXTRANET_SITE_TIMEOUT.getKey());
363     }
364 
365     public String getAuthenticationDefaultUsername() {
366         return applicationConfig.getOption(Quadrige2CoreConfigurationOption.AUTHENTICATION_DEFAULT_USERNAME.getKey());
367     }
368 
369     public String getAuthenticationDefaultPassword() {
370         return applicationConfig.getOption(Quadrige2CoreConfigurationOption.AUTHENTICATION_DEFAULT_PASSWORD.getKey());
371     }
372 
373     public String getAuthenticationMockUsername() {
374         return applicationConfig.getOption(Quadrige2CoreConfigurationOption.AUTHENTICATION_MOCK_USERNAME.getKey());
375     }
376 
377     public String getAuthenticationMockPassword() {
378         return applicationConfig.getOption(Quadrige2CoreConfigurationOption.AUTHENTICATION_MOCK_PASSWORD.getKey());
379     }
380 
381     public int getAuthenticationMockUserId() {
382         return applicationConfig.getOptionAsInt(Quadrige2CoreConfigurationOption.AUTHENTICATION_MOCK_USER_ID.getKey());
383     }
384 
385     /*
386      * Synchronization
387      */
388 
389     public boolean isSynchronizationUsingServer() {
390         return applicationConfig.getOptionAsBoolean(Quadrige2ConfigurationOption.SYNCHRONIZATION_USE_SERVER.getKey());
391     }
392 
393     public URL getSynchronizationSiteUrl() {
394         return getOptionAsURL(Quadrige2ConfigurationOption.SYNCHRONIZATION_SITE_URL.getKey());
395     }
396 
397     public Integer getSynchronizationSiteTimeout() {
398         return applicationConfig.getOptionAsInt(Quadrige2ConfigurationOption.SYNCHRONIZATION_SITE_TIMEOUT.getKey());
399     }
400 
401     /**
402      * <p>getSynchronizationRefreshTimeout.</p>
403      *
404      * @return a {@link java.lang.Integer} object.
405      */
406     public Integer getSynchronizationRefreshTimeout() {
407         return applicationConfig.getOptionAsInt(Quadrige2ConfigurationOption.SYNCHRONIZATION_REFRESH_TIMEOUT.getKey());
408     }
409 
410     /**
411      * <p>getSynchronizationRefreshTimeout.</p>
412      *
413      * @return a {@link java.lang.Integer} object.
414      */
415     public Integer getSynchronizationMaxRetryCount() {
416         return applicationConfig.getOptionAsInt(Quadrige2ConfigurationOption.SYNCHRONIZATION_RETRY_COUNT.getKey());
417     }
418 
419     /**
420      * <p>getSynchronizationRetryTimeout.</p>
421      *
422      * @return a {@link java.lang.Integer} object.
423      */
424     public Integer getSynchronizationRetryTimeout() {
425         return applicationConfig.getOptionAsInt(Quadrige2ConfigurationOption.SYNCHRONIZATION_RETRY_TIMEOUT.getKey());
426     }
427 
428     public File getSynchronizationDirectory() {
429         return applicationConfig.getOptionAsFile(Quadrige2ConfigurationOption.SYNCHRONIZATION_DIRECTORY.getKey());
430     }
431 
432     public boolean isSynchronizationEnabled() {
433         return (/*!isFullLaunchMode() ||*/ !isAuthenticationDisabled()) && getSynchronizationSiteUrl() != null;
434     }
435 
436     public boolean isSynchronizationPeriodSelectionEnable() {
437         return applicationConfig.getOptionAsBoolean(Quadrige2CoreConfigurationOption.SYNCHRONIZATION_PERIOD_SELECTION_ENABLE.getKey());
438     }
439 
440     public String getSynchroZipFilePrefix() {
441         return applicationConfig.getOption(Quadrige2CoreConfigurationOption.SYNCHRONIZATION_ZIP_FILE_PREFIX.getKey());
442     }
443 
444     public File getSynchroUserDirectory() {
445         return new File(getSynchronizationDirectory(), Integer.toString(SecurityContextHelper.getQuadrige2UserId()));
446     }
447 
448 
449     /*
450      * Application options
451      */
452 
453     /**
454      * Mode that enable : UI, automatic open DB, DB and application updated<br/>
455      *
456      * @return true if the full mode is enable
457      */
458     public boolean isFullLaunchMode() {
459         return "full".equals(getLaunchMode());
460     }
461 
462     /**
463      * Mode without UI and without automatic open DB <br/>
464      * Used for batch process (i.e. for backup action)
465      *
466      * @return true if the silent mode is enable
467      */
468     public boolean isSilentLaunchMode() {
469         return "silent".equals(getLaunchMode());
470     }
471 
472     /**
473      * <p>getLaunchMode.</p>
474      *
475      * @return a {@link java.lang.String} object.
476      */
477     public String getLaunchMode() {
478         return applicationConfig.getOption(Quadrige2CoreConfigurationOption.LAUNCH_MODE.getKey());
479     }
480 
481     /**
482      * <p>getAdminEmail.</p>
483      *
484      * @return a {@link java.lang.String} object, the admin email.
485      */
486     public String getAdminEmail() {
487         return applicationConfig.getOption(Quadrige2ConfigurationOption.ADMIN_EMAIL.getKey());
488     }
489 
490     /**
491      * <p>isShowFullConfigEnabled.</p>
492      *
493      * @return a boolean.
494      */
495     public boolean isShowFullConfigEnabled() {
496         return !isFullLaunchMode();
497     }
498 
499     public Locale getI18nLocale() {
500         return applicationConfig.getOptionAsLocale(Quadrige2CoreConfigurationOption.I18N_LOCALE.getKey());
501     }
502 
503     public void setI18nLocale(Locale locale) {
504         applicationConfig.setOption(Quadrige2CoreConfigurationOption.I18N_LOCALE.getKey(), locale.toString());
505     }
506 
507 
508     /*
509      * Utility methods
510      */
511 
512     public String getCsvSeparator() {
513         return applicationConfig.getOption(Quadrige2ConfigurationOption.CSV_SEPARATOR.getKey());
514     }
515 
516     public String getValueSeparator() {
517         return applicationConfig.getOption(Quadrige2ConfigurationOption.VALUE_SEPARATOR.getKey());
518     }
519 
520     public String getAttributeSeparator() {
521         return applicationConfig.getOption(Quadrige2ConfigurationOption.ATTRIBUTE_SEPARATOR.getKey());
522     }
523 
524     public File newTempFile(String basename) {
525         return new File(getTempDirectory(), basename + "_" + System.nanoTime());
526     }
527 
528     public File getConfigFile() {
529         if (configFile == null) {
530             File dir = getConfigDirectory();
531             if (dir == null || !dir.exists()) {
532                 dir = new File(applicationConfig.getUserConfigDirectory());
533             }
534             File originalConfigFile = new File(applicationConfig.getConfigFileName());
535             configFile = new File(dir, originalConfigFile.getName());
536         }
537         return configFile;
538     }
539 
540     public void overridesOptions(Properties options) {
541 
542         for (String key : options.stringPropertyNames()) {
543             String value = options.getProperty(key);
544             applicationConfig.setOption(key, value);
545         }
546 
547     }
548 
549     public void save() {
550 
551         File file = getConfigFile();
552         if (LOG.isDebugEnabled()) {
553             LOG.debug("Save configuration at: " + file);
554         }
555         try {
556             // Save into local user configuration file
557             applicationConfig.save(file, false, optionKeyToNotSave.toArray(new String[optionKeyToNotSave.size()]));
558         } catch (IOException e) {
559             throw new ApplicationTechnicalException(t("quadrige2.config.save.error", file), e);
560         }
561     }
562 
563 
564 
565     /*
566      * Internal methods
567      */
568 
569     protected URL getOptionAsURL(String key) {
570         String urlString = applicationConfig.getOption(key);
571 
572         // Could be empty (e.g. demo deployment)
573         if (StringUtils.isBlank(urlString)) {
574             return null;
575         }
576 
577         // correct end of the url string
578         if (!urlString.endsWith("/")) {
579             int schemeIndex = urlString.indexOf("://");
580             int firstSlashIndex = urlString.indexOf('/', schemeIndex + 3);
581             boolean addSlash = false;
582             if (firstSlashIndex == -1) {
583                 addSlash = true;
584             } else {
585                 int lastSlashIndex = urlString.lastIndexOf('/');
586                 if (lastSlashIndex > firstSlashIndex) {
587                     addSlash = urlString.indexOf('.', lastSlashIndex) == -1;
588                 }
589             }
590 
591             if (addSlash) {
592                 urlString += '/';
593             }
594         }
595 
596         URL url = null;
597         try {
598             url = new URL(urlString);
599         } catch (MalformedURLException ex) {
600             LOG.error(ex.getLocalizedMessage());
601         }
602 
603         return url;
604     }
605 
606     // TODO
607     public Color getColorBlockingLayer() {
608         return null;
609     }
610 
611 }