View Javadoc

1   /*
2    * SymmetricDS is an open source database synchronization solution.
3    *   
4    * Copyright (C) Chris Henson <chenson42@users.sourceforge.net>
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 3 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, see
18   * <http://www.gnu.org/licenses/>.
19   */
20  
21  package org.jumpmind.symmetric.service.impl;
22  
23  import java.math.BigDecimal;
24  import java.sql.ResultSet;
25  import java.sql.SQLException;
26  import java.util.Date;
27  import java.util.HashMap;
28  import java.util.Map;
29  import java.util.Properties;
30  import java.util.Set;
31  
32  import org.apache.commons.lang.StringUtils;
33  import org.apache.commons.logging.Log;
34  import org.apache.commons.logging.LogFactory;
35  import org.jumpmind.symmetric.common.Constants;
36  import org.jumpmind.symmetric.common.ParameterConstants;
37  import org.jumpmind.symmetric.config.IParameterFilter;
38  import org.jumpmind.symmetric.service.IParameterService;
39  import org.springframework.beans.BeansException;
40  import org.springframework.beans.factory.BeanFactory;
41  import org.springframework.beans.factory.BeanFactoryAware;
42  import org.springframework.jdbc.core.RowMapper;
43  
44  public class ParameterService extends AbstractService implements IParameterService, BeanFactoryAware {
45  
46      static final Log logger = LogFactory.getLog(ParameterService.class);
47  
48      private Map<String, String> parameters;
49  
50      private BeanFactory beanFactory;
51  
52      private long cacheTimeoutInMs = 0;
53  
54      private Date lastTimeParameterWereCached;
55  
56      private IParameterFilter parameterFilter;
57  
58      public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
59          this.beanFactory = beanFactory;
60      }
61  
62      public BigDecimal getDecimal(String key) {
63          String val = getString(key);
64          if (val != null) {
65              return new BigDecimal(val);
66          }
67          return BigDecimal.ZERO;
68      }
69  
70      public boolean is(String key) {
71          String val = getString(key);
72          if (val != null) {
73              if (val.equals("1")) {
74                  return true;
75              } else {
76                  return Boolean.parseBoolean(val);
77              }
78          } else {
79              return false;
80          }
81      }
82  
83      public int getInt(String key) {
84          String val = getString(key);
85          if (val != null) {
86              return Integer.parseInt(val);
87          }
88          return 0;
89      }
90  
91      public long getLong(String key) {
92          String val = getString(key);
93          if (val != null) {
94              return Long.parseLong(val);
95          }
96          return 0;
97      }
98  
99      public String getString(String key) {
100         String value = null;
101         // TODO remove in 2.0
102         if (!key.startsWith("symmetric.")) {
103             value = getString("symmetric." + key);
104             if (StringUtils.isBlank(value) && !key.startsWith("symmetric.runtime.")) {
105                 value = getString("symmetric.runtime." + key);
106             }
107         }
108 
109         if (StringUtils.isBlank(value)) {
110             value = getParameters().get(key);
111         }
112 
113         if (this.parameterFilter != null) {
114             value = this.parameterFilter.filterParameter(key, value);
115         }
116 
117         return value;
118     }
119 
120     public void saveParameter(String key, Object paramValue) {
121         this.saveParameter(getExternalId(), getNodeGroupId(), key, paramValue);
122     }
123 
124     public void saveParameter(String externalId, String nodeGroupId, String key, Object paramValue) {
125 
126         paramValue = paramValue != null ? paramValue.toString() : null;
127 
128         int count = jdbcTemplate.update(getSql("updateParameterSql"), new Object[] { paramValue, externalId,
129                 nodeGroupId, key });
130 
131         if (count == 0) {
132             jdbcTemplate
133                     .update(getSql("insertParameterSql"), new Object[] { externalId, nodeGroupId, key, paramValue });
134         }
135 
136         rereadParameters();
137     }
138 
139     public void saveParameters(String externalId, String nodeGroupId, Map<String, Object> parameters) {
140         Set<String> keys = parameters.keySet();
141         for (String key : keys) {
142             saveParameter(externalId, nodeGroupId, key, parameters.get(key));
143         }
144     }
145 
146     public synchronized void rereadParameters() {
147         this.parameters = null;
148         getParameters();
149     }
150 
151     /***
152      * Every time we pull the properties out of the bean factory they should get
153      * reread from the file system.
154      */
155     private Properties rereadFileParameters() {
156         return (Properties) beanFactory.getBean(Constants.PROPERTIES);
157     }
158 
159     private Map<String, String> rereadDatabaseParameters(Properties p) {
160         try {
161             Map<String, String> map = rereadDatabaseParameters(ALL, ALL);
162             map.putAll(rereadDatabaseParameters(ALL, p.getProperty(ParameterConstants.NODE_GROUP_ID)));
163             map.putAll(rereadDatabaseParameters(p.getProperty(ParameterConstants.EXTERNAL_ID), p
164                     .getProperty(ParameterConstants.NODE_GROUP_ID)));
165             return map;
166         } catch (Exception ex) {
167             logger.warn("Could not read the database parameters.  We will try again later.");
168             return new HashMap<String, String>();
169         }
170     }
171 
172     private Map<String, String> rereadDatabaseParameters(String externalId, String nodeGroupId) {
173         final Map<String, String> map = new HashMap<String, String>();
174         jdbcTemplate.query(getSql("selectParametersSql"), new Object[] { externalId, nodeGroupId }, new RowMapper() {
175             public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
176                 map.put(rs.getString(1), rs.getString(2));
177                 return null;
178             }
179         });
180         return map;
181     }
182 
183     private Map<String, String> buildSystemParameters() {
184         final Map<String, String> map = new HashMap<String, String>();
185         Properties p = rereadFileParameters();
186         for (Object key : p.keySet()) {
187             map.put((String) key, p.getProperty((String) key));
188         }
189         map.putAll(rereadDatabaseParameters(p));
190         return map;
191 
192     }
193 
194     private Map<String, String> getParameters() {
195         if (parameters == null
196                 || lastTimeParameterWereCached == null
197                 || (cacheTimeoutInMs > 0 && lastTimeParameterWereCached.getTime() < (System.currentTimeMillis() - cacheTimeoutInMs))) {
198             lastTimeParameterWereCached = new Date();
199             parameters = buildSystemParameters();
200             cacheTimeoutInMs = getInt(ParameterConstants.PARAMETER_REFRESH_PERIOD_IN_MS);
201             createRuntimeConfigIfNecessary();
202         }
203         return parameters;
204     }
205 
206     /***
207      * For backward compatibility only. Remove in 2.0.
208      */
209     @SuppressWarnings("deprecation")
210     private void createRuntimeConfigIfNecessary() {
211         String clazz = getString(ParameterConstants.RUNTIME_CONFIGURATION_CLASS);
212         if (parameterFilter == null && !StringUtils.isBlank(clazz)) {
213             try {
214                 final org.jumpmind.symmetric.config.IRuntimeConfig runtimeConfig = (org.jumpmind.symmetric.config.IRuntimeConfig) Class
215                         .forName(clazz).newInstance();
216                 parameterFilter = new IParameterFilter() {
217                     public String filterParameter(String key, String value) {
218                         if (key.equals(ParameterConstants.EXTERNAL_ID)) {
219                             return runtimeConfig.getExternalId();
220                         } else if (key.equals(ParameterConstants.NODE_GROUP_ID)) {
221                             return runtimeConfig.getNodeGroupId();
222                         } else if (key.equals(ParameterConstants.REGISTRATION_URL)) {
223                             return runtimeConfig.getRegistrationUrl();
224                         } else if (key.equals(ParameterConstants.SCHEMA_VERSION)) {
225                             return runtimeConfig.getSchemaVersion();
226                         } else if (key.equals(ParameterConstants.MY_URL)) {
227                             return runtimeConfig.getMyUrl();
228                         } else {
229                             return value;
230                         }
231                     }
232 
233                     public boolean isAutoRegister() {
234                         return false;
235                     }
236                 };
237 
238             } catch (Exception e) {
239                 logger.error(e);
240             }
241         }
242     }
243 
244     public Map<String, String> getAllParameters() {
245         return getParameters();
246     }
247 
248     public Date getLastTimeParameterWereCached() {
249         return lastTimeParameterWereCached;
250     }
251 
252     public void setParameterFilter(IParameterFilter parameterFilter) {
253         this.parameterFilter = parameterFilter;
254     }
255 
256     public String getExternalId() {
257         return getString(ParameterConstants.EXTERNAL_ID);
258     }
259 
260     public String getMyUrl() {
261         return getString(ParameterConstants.MY_URL);
262     }
263 
264     public String getNodeGroupId() {
265         return getString(ParameterConstants.NODE_GROUP_ID);
266     }
267 
268     public String getRegistrationUrl() {
269         return getString(ParameterConstants.REGISTRATION_URL);
270     }
271 
272 }