1 package org.naftulin.configmgr.parsers;
2
3 import java.net.URL;
4 import java.sql.Connection;
5 import java.sql.PreparedStatement;
6 import java.sql.ResultSet;
7 import java.sql.SQLException;
8 import java.util.HashMap;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Properties;
12
13 import javax.naming.InitialContext;
14 import javax.naming.NamingException;
15 import javax.sql.DataSource;
16
17 import org.apache.log4j.Logger;
18 import org.naftulin.configmgr.ConfigurationManagementEntry;
19 import org.naftulin.configmgr.ConfigurationManagementEntryImpl;
20 import org.naftulin.configmgr.ConfigurationManagerException;
21 import org.naftulin.configmgr.ConfigurationType;
22 import org.naftulin.configmgr.content.NameValuePairImpl;
23
24
25
26
27 public class DbJndiParserImpl extends AbstractJndiParser implements ConfigEntryParser {
28 private static final Logger log = Logger.getLogger(DbJndiParserImpl.class);
29
30 private static final long serialVersionUID = 1L;
31 private final String sql;
32 private final String keyColumnName;
33 private final String valueColumnName;
34
35
36
37 public DbJndiParserImpl(final String jndiName, final String initialContextFactory, final String sql,
38 final String keyColumnName, final String valueColumnName, final List<NameValuePairImpl> nameValuePairs) {
39 super(jndiName, initialContextFactory, nameValuePairs);
40 this.sql = sql;
41 this.keyColumnName = keyColumnName;
42 this.valueColumnName = valueColumnName;
43 }
44
45 /***
46 * Returns configuratoin management entry that contains a Map with key-value pairs read from the database based on the sql specified.
47 * The steps are: first database connection is established by looking up the database connection in JNDI based on JNDI name,
48 * JNDI Context factory if provided and other parameters as provided in cofiguration description.
49 * Second sql provided is executed against the database connection and lastly the results are read based on the columns provided in the
50 * configuration.
51 * @param key configuration management key
52 * @param fileUrl file url is null, since database configuration is not file URL based.
53 * @return Configuration management entry.
54 */
55 public ConfigurationManagementEntry getConfigurationManagementEntry(
56 final String key, final URL fileUrl) throws ConfigurationManagerException {
57 ConfigurationManagementEntry entry = null;
58
59 validateParameters(key);
60
61
62 final Properties jndiProperties = new Properties();
63 prepareJndiProperties(jndiProperties);
64
65 Connection c = null;
66 PreparedStatement stmt = null;
67 ResultSet rs = null;
68 try {
69 InitialContext context = null;
70 context = getJndiContext(key, jndiProperties, context);
71 log.info("Initial context created for JNDI name " + jndiName);
72
73 c = getJdbcConnection(key, context);
74 log.info("Connected to the database by JNDI name " + jndiName + " and sql " + sql);
75
76 stmt = c.prepareStatement(sql);
77 log.debug("Statment perpared " + sql + " for database jndi name " + jndiName);
78
79 rs = stmt.executeQuery();
80 log.debug("Received result set for sql " + sql);
81
82 entry = createEntryBasedOnNameValuePairs(key, rs);
83 log.info("configuration management entry created for key " + key + " with sql " + sql);
84 } catch (SQLException e) {
85 log.error("Could not connect to the database using jndi name: " + jndiName + " sql " + sql + " and other parameters from configuration " + key, e);
86 throw new ConfigurationManagerException("Could not connect to the database using jndiName: " + jndiName + " sql " + sql + " and other parameters from configuration " + key, e);
87 } finally {
88 DBUtils.closeResultSet(rs);
89 DBUtils.closeStatement(stmt);
90 DBUtils.closeConnection(c);
91 }
92
93 return entry;
94 }
95
96 private ConfigurationManagementEntry createEntryBasedOnNameValuePairs(
97 final String key, final ResultSet rs) throws SQLException {
98 ConfigurationManagementEntry entry;
99 final Map<String, String> configuration = new HashMap<String, String>();
100 String mapKey = null;
101 String mapValue = null;
102 while(rs.next()) {
103 mapKey = rs.getString(keyColumnName);
104 mapValue = rs.getString(valueColumnName);
105 log.debug("getting key " + mapKey + " value " + mapValue + " for sql " + sql);
106 configuration.put(mapKey, mapValue);
107 }
108 final String fileName = "jndiName : " + jndiName + " sql " + sql;
109
110 entry = new ConfigurationManagementEntryImpl(key, fileName, configuration, this, ConfigurationType.DB_JNDI);
111 return entry;
112 }
113
114 private Connection getJdbcConnection(final String key, final InitialContext context) throws SQLException, ConfigurationManagerException {
115 Connection c = null;
116 try {
117 final DataSource dc = (DataSource) context.lookup(jndiName);
118 c = dc.getConnection();
119 } catch (NamingException e) {
120 log.error("Could not lookup jndi name: " + jndiName + " sql " + sql + " and other parameters from configuration " + key, e);
121 throw new ConfigurationManagerException("Could not lookup jndi name: " + jndiName + " sql " + sql + " and other parameters from configuration " + key, e);
122 }
123 return c;
124 }
125
126 /***
127 * Validates that key, jndi name, sql, etc are not null parameters
128 * @param key
129 * @throws ConfigurationManagerException
130 */
131 protected void validateParameters(final String key) throws ConfigurationManagerException {
132 super.validateParameters(key);
133 if (sql == null) {
134 throw new ConfigurationManagerException("sql is null, please provide sql in you master configuraton file for external cofiguraton with key =" + key);
135 }
136 if (keyColumnName == null) {
137 throw new ConfigurationManagerException("keyColumnName is null, please provide key column name in you master configuraton file for external cofiguraton with key =" + key);
138 }
139 if (valueColumnName == null) {
140 throw new ConfigurationManagerException("valueColumnName is null, please provide valueColumnName in you master configuraton file for external cofiguraton with key =" + key);
141 }
142 }
143
144
145
146 }