1 package org.naftulin.configmgr.parsers;
2
3 import java.net.URL;
4 import java.sql.Connection;
5 import java.sql.DriverManager;
6 import java.sql.PreparedStatement;
7 import java.sql.ResultSet;
8 import java.sql.SQLException;
9 import java.util.HashMap;
10 import java.util.Iterator;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Properties;
14
15 import org.apache.log4j.Logger;
16 import org.naftulin.configmgr.ConfigurationManagementEntry;
17 import org.naftulin.configmgr.ConfigurationManagementEntryImpl;
18 import org.naftulin.configmgr.ConfigurationManagerException;
19 import org.naftulin.configmgr.ConfigurationType;
20 import org.naftulin.configmgr.content.AbstractRecordImpl;
21 import org.naftulin.configmgr.content.NameValuePairImpl;
22
23
24
25
26 public class DbDirectParserImpl implements ConfigEntryParser {
27 private static final Logger log = Logger.getLogger(ConfigEntryParser.class);
28
29 private static final long serialVersionUID = 1L;
30 private final String driverClass;
31 private final String connectionUrl;
32 private final String sql;
33 private final String user;
34 private final String password;
35 private final String keyColumnName;
36 private final String valueColumnName;
37 private List<NameValuePairImpl> nameValuePairs;
38
39
40
41 public DbDirectParserImpl(final String driverClass, final String connectionUrl, final String sql,
42 final String user, final String password, final String keyColumnName,
43 final String valueColumnName, final List<NameValuePairImpl> nameValuePairs) {
44 super();
45 this.driverClass = driverClass;
46 this.connectionUrl = connectionUrl;
47 this.sql = sql;
48 this.user = user;
49 this.password = password;
50 this.keyColumnName = keyColumnName;
51 this.valueColumnName = valueColumnName;
52 this.nameValuePairs = nameValuePairs;
53 }
54
55 /***
56 * Returns configuratoin management entry that contains a Map with key-value pairs read from the database based on the sql specified.
57 * The steps are: first database connection is established by loading the database driver and connecting to the database using database URL
58 * and user/ password if provided with any other connection specific properties if provided in configuration description.
59 * Second sql provided is executed against the database connection and lastly the results are read based on the columns provided in the
60 * configuration.
61 * @param key configuration management key
62 * @param fileUrl file url is null, since database configuration is not file URL based.
63 * @return Configuration management entry.
64 */
65 public ConfigurationManagementEntry getConfigurationManagementEntry(
66 final String key, final URL fileUrl) throws ConfigurationManagerException {
67 ConfigurationManagementEntry entry = null;
68
69 validateParameters(key);
70
71
72 loadJdbcDriverClass(key);
73 log.info("Driver class " + driverClass + " is loaded.");
74
75 final Properties props = new Properties();
76 prepareJdbcConnectionProperties(props);
77
78 Connection c = null;
79 PreparedStatement stmt = null;
80 ResultSet rs = null;
81 try {
82 c = DriverManager.getConnection(connectionUrl, props);
83 log.info("Connected to the database " + connectionUrl + " and sql " + sql);
84
85 stmt = c.prepareStatement(sql);
86 log.debug("Statment perpared " + sql + " for database " + connectionUrl);
87
88 rs = stmt.executeQuery();
89 log.debug("Received result set for sql " + sql);
90
91 entry = createEntryBasedOnResultSet(key, rs);
92 log.info("configuration management entry created for key " + key + " with sql " + sql);
93 } catch (SQLException e) {
94 log.error("Could not connect to the database using driver class: " + driverClass + " url " + connectionUrl + " sql " + sql + " and other parameters from configuration " + key, e);
95 throw new ConfigurationManagerException("Could not connect to the database using driver class: " + driverClass + " url " + connectionUrl + " sql " + sql + " and other parameters from configuration " + key, e);
96 } finally {
97 DBUtils.closeResultSet(rs);
98 DBUtils.closeStatement(stmt);
99 DBUtils.closeConnection(c);
100 }
101
102 return entry;
103 }
104
105 private ConfigurationManagementEntry createEntryBasedOnResultSet(
106 final String key, final ResultSet rs) throws SQLException {
107 ConfigurationManagementEntry entry;
108 final Map<String, String> configuration = new HashMap<String, String>();
109 String mapKey = null;
110 String mapValue = null;
111 while(rs.next()) {
112 mapKey = rs.getString(keyColumnName);
113 mapValue = rs.getString(valueColumnName);
114 log.debug("getting key " + mapKey + " value " + mapValue + " for sql " + sql);
115 configuration.put(mapKey, mapValue);
116 }
117 final String fileName = "driver : " + driverClass + " connection " + connectionUrl + " sql " + sql + " user " + user;
118
119 entry = new ConfigurationManagementEntryImpl(key, fileName, configuration, this, ConfigurationType.DB_DIRECT);
120 return entry;
121 }
122
123 private void prepareJdbcConnectionProperties(final Properties props) {
124 if (user != null) { props.put("user", user); }
125 if (password != null) { props.put("password", password); }
126
127 final Iterator<NameValuePairImpl> it = nameValuePairs.iterator();
128 while(it.hasNext()) {
129 NameValuePairImpl nvp = it.next();
130 props.put(nvp.getName(), nvp.getValue());
131 }
132 }
133
134 private void loadJdbcDriverClass(final String key) throws ConfigurationManagerException {
135 try {
136 Class.forName(driverClass);
137 } catch(Exception e) {
138 log.error("Could not load driver class: " + driverClass + " for configuration " + key, e);
139 throw new ConfigurationManagerException("Could not load driver class: " + driverClass + " for configuration " + key, e);
140 }
141 }
142
143 private void validateParameters(final String key) throws ConfigurationManagerException {
144 if (key == null) {
145 throw new ConfigurationManagerException("key is null, please provide the key in you master configuraton file for all the db direct cofigurations");
146 }
147 if (driverClass == null) {
148 throw new ConfigurationManagerException("driverClass is null, please provide driver class in you master configuraton file for external cofiguraton with key =" + key);
149 }
150 if (sql == null) {
151 throw new ConfigurationManagerException("sql is null, please provide sql in you master configuraton file for external cofiguraton with key =" + key);
152 }
153 if (keyColumnName == null) {
154 throw new ConfigurationManagerException("keyColumnName is null, please provide key column name in you master configuraton file for external cofiguraton with key =" + key);
155 }
156 if (valueColumnName == null) {
157 throw new ConfigurationManagerException("valueColumnName is null, please provide valueColumnName in you master configuraton file for external cofiguraton with key =" + key);
158 }
159 }
160
161
162 public String getDriverClass() {
163 return driverClass;
164 }
165
166 public String getKeyColumnName() {
167 return keyColumnName;
168 }
169
170
171 public List<NameValuePairImpl> getNameValuePairs() {
172 return nameValuePairs;
173 }
174
175
176 public String getPassword() {
177 return password;
178 }
179
180
181 public String getSql() {
182 return sql;
183 }
184
185
186 public String getUser() {
187 return user;
188 }
189
190
191 public String getValueColumnName() {
192 return valueColumnName;
193 }
194
195 public String getConnectionUrl() {
196 return this.connectionUrl;
197 }
198
199 }