001package fr.ifremer.adagio.core.config;
002
003/*
004 * #%L
005 * SIH-Adagio :: Core for Allegro
006 * $Id:$
007 * $HeadURL:$
008 * %%
009 * Copyright (C) 2012 - 2013 Ifremer
010 * %%
011 * This program is free software: you can redistribute it and/or modify
012 * it under the terms of the GNU Affero General Public License as published by
013 * the Free Software Foundation, either version 3 of the License, or
014 * (at your option) any later version.
015 * 
016 * This program is distributed in the hope that it will be useful,
017 * but WITHOUT ANY WARRANTY; without even the implied warranty of
018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
019 * GNU General Public License for more details.
020 * 
021 * You should have received a copy of the GNU Affero General Public License
022 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
023 * #L%
024 */
025
026import static org.nuiton.i18n.I18n.t;
027
028import java.io.File;
029import java.util.Arrays;
030import java.util.List;
031import java.util.Locale;
032import java.util.Properties;
033import java.util.Set;
034
035import org.apache.commons.collections4.CollectionUtils;
036import org.apache.commons.lang3.ArrayUtils;
037import org.apache.commons.logging.Log;
038import org.apache.commons.logging.LogFactory;
039import org.nuiton.config.ApplicationConfig;
040import org.nuiton.config.ApplicationConfigHelper;
041import org.nuiton.config.ApplicationConfigProvider;
042import org.nuiton.config.ArgumentsParserException;
043import org.nuiton.util.Version;
044import org.springframework.beans.BeansException;
045import org.springframework.beans.factory.BeanInitializationException;
046import org.springframework.beans.factory.InitializingBean;
047import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
048import org.springframework.context.ApplicationContext;
049import org.springframework.context.ApplicationContextAware;
050import org.springframework.core.io.Resource;
051
052import com.google.common.base.Charsets;
053
054import fr.ifremer.adagio.core.AdagioTechnicalException;
055import fr.ifremer.adagio.core.dao.technical.DaoUtils;
056import fr.ifremer.adagio.core.service.technical.SpringUtils;
057
058public class AdagioConfiguration extends PropertyPlaceholderConfigurer implements ApplicationContextAware, InitializingBean {
059    /** Logger. */
060    private static final Log log = LogFactory.getLog(AdagioConfiguration.class);
061
062    /**
063     * Delegate application config.
064     */
065    protected final ApplicationConfig applicationConfig;
066
067    private static AdagioConfiguration instance;
068
069    public static AdagioConfiguration getInstance() {
070        return instance;
071    }
072
073    public static void setInstance(AdagioConfiguration instance) {
074        AdagioConfiguration.instance = instance;
075    }
076
077    protected final String[] optionKeyToNotSave;
078
079    protected File configFile;
080
081    private ApplicationContext appContext = null;
082
083    private boolean isInitialize = false;
084
085    public AdagioConfiguration(ApplicationConfig applicationConfig) {
086        super();
087        this.applicationConfig = applicationConfig;
088        this.optionKeyToNotSave = null;
089    }
090
091    public AdagioConfiguration(String file, String... args) {
092        super();
093        this.applicationConfig = new ApplicationConfig();
094        this.applicationConfig.setEncoding(Charsets.UTF_8.name());
095        this.applicationConfig.setConfigFileName(file);
096
097        // get all config providers
098        Set<ApplicationConfigProvider> providers =
099                ApplicationConfigHelper.getProviders(null,
100                        null,
101                        null,
102                        true);
103
104        // load all default options
105        ApplicationConfigHelper.loadAllDefaultOption(applicationConfig,
106                providers);
107
108        // Load actions
109        for (ApplicationConfigProvider provider : providers) {
110            applicationConfig.loadActions(provider.getActions());
111        }
112        
113        // Define Alias
114        addAlias(applicationConfig);
115
116        // get all transient and final option keys
117        Set<String> optionToSkip =
118                ApplicationConfigHelper.getTransientOptionKeys(providers);
119
120        if (log.isDebugEnabled()) {
121            log.debug("Option that won't be saved: " + optionToSkip);
122        }
123        optionKeyToNotSave = optionToSkip.toArray(new String[optionToSkip.size()]);
124
125        try {
126            applicationConfig.parse(args);
127
128        } catch (ArgumentsParserException e) {
129            throw new AdagioTechnicalException(t("adagio.config.parse.error"), e);
130        }
131
132        // TODO Review this, this is very dirty to do this...
133        File allegroBasedir = applicationConfig.getOptionAsFile(
134                AdagioConfigurationOption.BASEDIR.getKey());
135
136        if (allegroBasedir == null) {
137            allegroBasedir = new File("");
138        }
139        if (!allegroBasedir.isAbsolute()) {
140            allegroBasedir = new File(allegroBasedir.getAbsolutePath());
141        }
142        if (allegroBasedir.getName().equals("..")) {
143            allegroBasedir = allegroBasedir.getParentFile().getParentFile();
144        }
145        if (allegroBasedir.getName().equals(".")) {
146            allegroBasedir = allegroBasedir.getParentFile();
147        }
148        if (log.isInfoEnabled()) {
149            log.info("Application basedir: " + allegroBasedir);
150        }
151        applicationConfig.setOption(
152                AdagioConfigurationOption.BASEDIR.getKey(),
153                allegroBasedir.getAbsolutePath());
154    }
155
156    /**
157     * Add alias to the given ApplicationConfig. <p/>
158     * This method could be override to add specific alias
159     * 
160     * @param applicationConfig
161     */
162    protected void addAlias(ApplicationConfig applicationConfig) {
163        applicationConfig.addAlias("-u", "--option", AdagioConfigurationOption.JDBC_USERNAME.getKey());
164        applicationConfig.addAlias("--user", "--option", AdagioConfigurationOption.JDBC_USERNAME.getKey());
165        applicationConfig.addAlias("-p", "--option", AdagioConfigurationOption.JDBC_PASSWORD.getKey());
166        applicationConfig.addAlias("--password", "--option", AdagioConfigurationOption.JDBC_PASSWORD.getKey());
167        applicationConfig.addAlias("-db", "--option", AdagioConfigurationOption.JDBC_URL.getKey());
168        applicationConfig.addAlias("--database", "--option", AdagioConfigurationOption.JDBC_URL.getKey());
169        applicationConfig.addAlias("--output", "--option", AdagioConfigurationOption.LIQUIBASE_OUTPUT_FILE.getKey());
170        applicationConfig.addAlias("--port", "--option", AdagioConfigurationOption.SERVER_PORT.getKey());
171
172    }
173
174    @Override
175    public void setApplicationContext(ApplicationContext appContext) throws BeansException {
176        this.appContext = appContext;
177    }
178
179    @Override
180    public void afterPropertiesSet() throws Exception {
181
182        if (isInitialize) {
183            return;
184        }
185        isInitialize = true;
186
187        // Retrieve paths from configuration
188        String[] enumerationFilePaths = getEnumerationFilesPath();
189        if (ArrayUtils.isEmpty(enumerationFilePaths)) {
190            throw new BeanInitializationException(
191                    String.format(
192                            "No enumeration files path has been set in the configuration. This is need to initialize enumeration values. Please set the option [%s] in configuration file.",
193                            AdagioConfigurationOption.DB_ENUMERATION_RESOURCE));
194        }
195        if (log.isDebugEnabled()) {
196            log.debug(String.format("Getting enumeration files from path: %s", Arrays.toString(enumerationFilePaths)));
197        }
198
199        // For each path, retrieve corresponding resources
200        List<Resource> resources = SpringUtils.getResourcesFromPaths(enumerationFilePaths, appContext, true);
201
202        // Check if some files has been found
203        if (CollectionUtils.isEmpty(resources)) {
204            throw new BeanInitializationException(String.format("No enumeration files could be found from path %s",
205                    Arrays.toString(enumerationFilePaths)));
206        }
207        if (log.isDebugEnabled()) {
208            log.debug(String.format("%s enumeration files found from path: %s", resources.size(), Arrays.toString(enumerationFilePaths)));
209        }
210
211        // Set enumeration default values (from enumeration file)
212        AdagioEnumerationHelper.reload(applicationConfig, resources);
213    }
214
215    public File getConfigFile() {
216        if (configFile == null) {
217            File dir = getBasedir();
218            if (dir == null || !dir.exists()) {
219                dir = new File(applicationConfig.getUserConfigDirectory());
220            }
221            configFile = new File(dir, applicationConfig.getConfigFileName());
222        }
223        return configFile;
224    }
225
226    /** @return {@link AdagioConfigurationOption#BASEDIR} value */
227    public File getBasedir() {
228        File result = applicationConfig.getOptionAsFile(AdagioConfigurationOption.BASEDIR.getKey());
229        return result;
230    }
231
232    /** @return {@link AdagioConfigurationOption#DATA_DIRECTORY} value */
233    public File getDataDirectory() {
234        File result = applicationConfig.getOptionAsFile(AdagioConfigurationOption.DATA_DIRECTORY.getKey());
235        return result;
236    }
237
238    public ApplicationConfig getApplicationConfig() {
239        return applicationConfig;
240    }
241
242    @Override
243    protected String resolvePlaceholder(String placeholder, Properties props) {
244        if (applicationConfig == null) {
245            throw new AdagioTechnicalException(
246                    "AdagioConfiguration.applicationConfig must not be null. Please initialize AdagioConfiguration instance with a not null applicationConfig BEFORE starting Spring.");
247        }
248
249        // Try to resolve placeholder from application configuration
250        String optionValue = applicationConfig.getOption(placeholder);
251        if (optionValue != null) {
252            return optionValue;
253        }
254
255        // If not found in configuration, delegate to the default Spring mecanism
256        return super.resolvePlaceholder(placeholder, props);
257    }
258
259    public File getDbDirectory() {
260        return applicationConfig.getOptionAsFile(AdagioConfigurationOption.DB_DIRECTORY.getKey());
261    }
262
263    public void setDbDirectory(File dbDirectory) {
264        applicationConfig.setOption(AdagioConfigurationOption.DB_DIRECTORY.getKey(), dbDirectory.getPath());
265    }
266
267    public File getDbAttachmentDirectory() {
268        return applicationConfig.getOptionAsFile(AdagioConfigurationOption.DB_ATTACHMENT_DIRECTORY.getKey());
269    }
270
271    public File getCacheDirectory() {
272        return applicationConfig.getOptionAsFile(AdagioConfigurationOption.DB_CACHE_DIRECTORY.getKey());
273    }
274
275    public File getDbBackupDirectory() {
276        return applicationConfig.getOptionAsFile(AdagioConfigurationOption.DB_BACKUP_DIRECTORY.getKey());
277    }
278
279    public boolean useBacthTreeCache() {
280        return applicationConfig.getOptionAsBoolean(AdagioConfigurationOption.CACHE_BACTH_TREE.getKey());
281    }
282
283    public boolean useLiquibaseAutoRun() {
284        return applicationConfig.getOptionAsBoolean(AdagioConfigurationOption.LIQUIBASE_RUN_AUTO.getKey());
285    }
286
287    public String getLiquibaseChangeLogPath() {
288        return applicationConfig.getOption(AdagioConfigurationOption.LIQUIBASE_CHANGE_LOG_PATH.getKey());
289    }
290
291    public String getHibernateDialect() {
292        return applicationConfig.getOption(AdagioConfigurationOption.HIBERNATE_DIALECT.getKey());
293    }
294
295    public String getHibernateClientQueriesFile() {
296        return applicationConfig.getOption(AdagioConfigurationOption.HIBERNATE_CLIENT_QUERIES_FILE.getKey());
297    }
298
299    public String getJdbcDriver() {
300        return applicationConfig.getOption(AdagioConfigurationOption.JDBC_DRIVER.getKey());
301    }
302
303    public String getJdbcURL() {
304        return applicationConfig.getOption(AdagioConfigurationOption.JDBC_URL.getKey());
305    }
306
307    public String getJdbcCatalog() {
308        return applicationConfig.getOption(AdagioConfigurationOption.JDBC_SCHEMA.getKey());
309    }
310
311    public String getJdbcSchema() {
312        return applicationConfig.getOption(AdagioConfigurationOption.JDBC_SCHEMA.getKey());
313    }
314
315    public boolean debugEntityLoad() {
316        return applicationConfig.getOptionAsBoolean(AdagioConfigurationOption.DEBUG_ENTITY_LOAD.getKey());
317    }
318
319    public String[] getEnumerationFilesPath() {
320        String enumerationFilesPath = applicationConfig.getOption(AdagioConfigurationOption.DB_ENUMERATION_RESOURCE.getKey());
321        String[] enumerationFilesPathArray = enumerationFilesPath.split(",");
322        return enumerationFilesPathArray;
323    }
324
325    public String getDbName() {
326        return applicationConfig.getOption(AdagioConfigurationOption.DB_NAME.getKey());
327    }
328
329    public String getDbValidationQuery() {
330        return applicationConfig.getOption(AdagioConfigurationOption.DB_VALIDATION_QUERY.getKey());
331    }
332
333    public String getJdbcUsername() {
334        return applicationConfig.getOption(AdagioConfigurationOption.JDBC_USERNAME.getKey());
335    }
336
337    public String getJdbcPassword() {
338        return applicationConfig.getOption(AdagioConfigurationOption.JDBC_PASSWORD.getKey());
339    }
340
341    public int getJdbcBatchSize() {
342        return applicationConfig.getOptionAsInt(AdagioConfigurationOption.JDBC_BATCH_SIZE.getKey());
343    }
344
345    public String getStatusCodeTemporary() {
346        return applicationConfig.getOption(AdagioConfigurationOption.STATUS_CODE_TEMPORARY.getKey());
347    }
348
349    public String getStatusCodeValid() {
350        return applicationConfig.getOption(AdagioConfigurationOption.STATUS_CODE_ENABLE.getKey());
351    }
352
353    public Version getVersion() {
354        return applicationConfig.getOptionAsVersion(AdagioConfigurationOption.VERSION.getKey());
355    }
356
357    public String getVesselRegistryProgramCode() {
358        return applicationConfig.getOption(AdagioConfigurationOption.PROGRAM_CODE_VESSEL_REGISTRY.getKey());
359    }
360
361    public File getI18nDirectory() {
362        return applicationConfig.getOptionAsFile(
363                AdagioConfigurationOption.I18N_DIRECTORY.getKey());
364    }
365
366    public Locale getI18nLocale() {
367        return applicationConfig.getOptionAsLocale(
368                AdagioConfigurationOption.I18N_LOCALE.getKey());
369    }
370
371    public void setI18nLocale(Locale locale) {
372        applicationConfig.setOption(AdagioConfigurationOption.I18N_LOCALE.getKey(), locale.toString());
373    }
374
375    public Properties getConnectionProperties() {
376        return DaoUtils.getConnectionProperties(
377                getJdbcURL(),
378                getJdbcUsername(),
379                getJdbcPassword(),
380                null,
381                getHibernateDialect(),
382                getJdbcDriver());
383    }
384
385    public String getLiquibaseDiffTypes() {
386        return applicationConfig.getOption(AdagioConfigurationOption.LIQUIBASE_DIFF_TYPES.getKey());
387    }
388
389    public File getLiquibaseOutputFile() {
390        return applicationConfig.getOptionAsFile(AdagioConfigurationOption.LIQUIBASE_OUTPUT_FILE.getKey());
391    }
392
393    public Integer getServerPort() {
394        return applicationConfig.getOptionAsInt(AdagioConfigurationOption.SERVER_PORT.getKey());
395    }
396}