View Javadoc

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  		// at this point connect to the database, and get the info
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 		//construct the configuration entry
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 }