View Javadoc
1   package net.sumaris.core.service.technical;
2   
3   /*-
4    * #%L
5    * SUMARiS:: Core
6    * %%
7    * Copyright (C) 2018 - 2019 SUMARiS Consortium
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/gpl-3.0.html>.
22   * #L%
23   */
24  
25  import com.google.common.base.Preconditions;
26  import net.sumaris.core.config.SumarisConfiguration;
27  import net.sumaris.core.config.SumarisConfigurationOption;
28  import net.sumaris.core.dao.schema.DatabaseSchemaDao;
29  import net.sumaris.core.dao.technical.SoftwareDao;
30  import net.sumaris.core.exception.VersionNotFoundException;
31  import net.sumaris.core.vo.technical.SoftwareVO;
32  import org.apache.commons.collections4.MapUtils;
33  import org.apache.commons.logging.Log;
34  import org.apache.commons.logging.LogFactory;
35  import org.nuiton.config.ApplicationConfig;
36  import org.nuiton.config.ApplicationConfigHelper;
37  import org.nuiton.config.ApplicationConfigProvider;
38  import org.nuiton.version.Version;
39  import org.nuiton.version.VersionBuilder;
40  import org.springframework.beans.factory.annotation.Autowired;
41  import org.springframework.context.annotation.Bean;
42  import org.springframework.stereotype.Component;
43  
44  import javax.annotation.PostConstruct;
45  import java.io.BufferedReader;
46  import java.io.InputStreamReader;
47  import java.net.URL;
48  import java.util.Optional;
49  import java.util.Set;
50  import java.util.stream.Collectors;
51  import java.util.stream.Stream;
52  
53  
54  @Component("softwareService")
55  public class SoftwareServiceImpl implements SoftwareService {
56  
57      private static final Log log = LogFactory.getLog(SoftwareServiceImpl.class);
58  
59      @Autowired
60      private SoftwareDao dao;
61  
62      @Autowired
63      private DatabaseSchemaDao databaseSchemaDao;
64  
65      private String defaultSoftwareLabel;
66  
67  
68      public SoftwareServiceImpl(SumarisConfiguration configuration) {
69          this.defaultSoftwareLabel = configuration.getAppName();
70          Preconditions.checkNotNull(defaultSoftwareLabel);
71      }
72  
73      @PostConstruct
74      protected void afterPropertiesSet() {
75  
76          loadConfigurationFromDatabase();
77      }
78  
79      @Override
80      public SoftwareVO getDefault() {
81          return dao.get(defaultSoftwareLabel);
82      }
83  
84      @Override
85      public SoftwareVO get(String label) {
86          Preconditions.checkNotNull(label);
87  
88          return dao.get(label);
89      }
90  
91      @Override
92      public SoftwareVO"../../../../../net/sumaris/core/vo/technical/SoftwareVO.html#SoftwareVO">SoftwareVO save(SoftwareVO source) {
93          Preconditions.checkNotNull(source);
94          Preconditions.checkNotNull(source.getLabel());
95  
96          return dao.save(source);
97      }
98  
99      /**
100      * Auto detect IP
101      *
102      * @return the IP address or null
103      */
104     @Bean
105     private Optional<String> whatsMyIp() {
106 
107         try {
108             URL whatismyip = new URL("http://checkip.amazonaws.com");
109             BufferedReader in = new BufferedReader(new InputStreamReader(whatismyip.openStream()));
110             return Optional.of(in.readLine());
111         } catch (Exception e) {
112             return Optional.empty();
113         }
114     }
115 
116     protected void loadConfigurationFromDatabase() {
117 
118         try {
119             Version dbVersion = databaseSchemaDao.getSchemaVersion();
120             Version minVersion = VersionBuilder.create("0.9.5").build();
121 
122             // Test if software table exists, if not, skip
123             if (dbVersion == null || minVersion.after(dbVersion)) {
124                 log.warn(String.format("Skipping configuration override from database (expected min schema version {%s})", minVersion.toString()));
125                 return; // skip
126             }
127         } catch(VersionNotFoundException e) {
128             // ok, continue (schema should be a new one ?)
129         }
130 
131         ApplicationConfig appConfig = SumarisConfiguration.getInstance().getApplicationConfig();
132         // Override the configuration existing in the config file, using DB
133         SoftwareVO software = getDefault();
134         if (software == null) {
135             log.info(String.format("No configuration for {%s} found in database. to enable configuration override from database, make sure to set the option '%s' to an existing row of the table SOFTWARE (column LABEL).", defaultSoftwareLabel, SumarisConfigurationOption.APP_NAME.getKey()));
136         }
137         else if (MapUtils.isNotEmpty(software.getProperties())) {
138             log.info(String.format("Overriding configuration options, using those found in database for {%s}", defaultSoftwareLabel));
139 
140             // Load options from configuration providers
141             Set<ApplicationConfigProvider> providers =
142                     ApplicationConfigHelper.getProviders(null,
143                             null,
144                             null,
145                             true);
146             Set<String> optionKeys = providers.stream().flatMap(p -> Stream.of(p.getOptions()))
147                     .map(o -> o.getKey()).collect(Collectors.toSet());
148             Set<String> transientOptionKeys = providers.stream().flatMap(p -> Stream.of(p.getOptions()))
149                     .filter(o -> o.isTransient())
150                     .map(o -> o.getKey()).collect(Collectors.toSet());
151 
152             software.getProperties().entrySet()
153                     .forEach(entry -> {
154                         if (!optionKeys.contains(entry.getKey())) {
155                             if (log.isDebugEnabled()) log.debug(String.format(" - Skipping unknown configuration option {%s=%s} found in database for {%s}.", entry.getKey(), entry.getValue(), defaultSoftwareLabel));
156                         }
157                         else if (transientOptionKeys.contains(entry.getKey())) {
158                             if (log.isDebugEnabled()) log.debug(String.format(" - Skipping transient configuration option {%s=%s} found in database for {%s}.", entry.getKey(), entry.getValue(), defaultSoftwareLabel));
159                         }
160                         else {
161                             if (log.isDebugEnabled()) log.debug(String.format(" - Applying option {%s=%s}", entry.getKey(), entry.getValue()));
162 
163                             appConfig.setOption(entry.getKey(), entry.getValue());
164                         }
165                     });
166         }
167     }
168 
169 }