1 19 20 package org.apache.cayenne.conf; 21 22 import java.io.BufferedReader ; 23 import java.io.IOException ; 24 import java.io.InputStream ; 25 import java.io.InputStreamReader ; 26 import java.net.MalformedURLException ; 27 import java.net.URL ; 28 29 import javax.sql.DataSource ; 30 31 import org.apache.cayenne.ConfigurationException; 32 import org.apache.cayenne.access.ConnectionLogger; 33 import org.apache.cayenne.access.QueryLogger; 34 import org.apache.cayenne.conn.DataSourceInfo; 35 import org.apache.cayenne.conn.PoolManager; 36 import org.apache.cayenne.util.Util; 37 import org.apache.commons.logging.Log; 38 import org.apache.commons.logging.LogFactory; 39 import org.xml.sax.Attributes ; 40 import org.xml.sax.ContentHandler ; 41 import org.xml.sax.InputSource ; 42 import org.xml.sax.SAXException ; 43 import org.xml.sax.XMLReader ; 44 import org.xml.sax.helpers.DefaultHandler ; 45 46 52 public class DriverDataSourceFactory implements DataSourceFactory { 56 57 private static final Log logger = LogFactory.getLog(DriverDataSourceFactory.class); 58 59 protected XMLReader parser; 60 protected DataSourceInfo driverInfo; 61 protected Configuration parentConfiguration; 62 63 66 public DriverDataSourceFactory() throws Exception { 67 this.parser = Util.createXmlReader(); 68 } 69 70 73 public void initializeWithParentConfiguration(Configuration parentConfiguration) { 74 this.parentConfiguration = parentConfiguration; 75 } 76 77 public DataSource getDataSource(String location) throws Exception { 78 this.load(location); 79 80 ConnectionLogger logger = new ConnectionLogger(); 81 82 try { 83 return new PoolManager(driverInfo.getJdbcDriver(), driverInfo 84 .getDataSourceUrl(), driverInfo.getMinConnections(), driverInfo 85 .getMaxConnections(), driverInfo.getUserName(), driverInfo 86 .getPassword(), logger); 87 } 88 catch (Exception ex) { 89 QueryLogger.logConnectFailure(ex); 90 throw ex; 91 } 92 } 93 94 97 protected DataSourceInfo getDriverInfo() { 98 return this.driverInfo; 99 } 100 101 protected InputStream getInputStream(String location) { 102 if (this.parentConfiguration == null) { 103 throw new ConfigurationException( 104 "No parent Configuration set - cannot continue."); 105 } 106 107 return this.parentConfiguration.getResourceLocator().findResourceStream(location); 108 } 109 110 114 protected void load(String location) throws Exception { 115 logger.info("loading driver information from '" + location + "'."); 116 117 InputStream in = this.getInputStream(location); 118 if (in == null) { 119 logger.info("Error: location '" + location + "' not found."); 120 throw new ConfigurationException( 121 "Can't find DataSource configuration file at " + location); 122 } 123 124 RootHandler handler = new RootHandler(); 125 parser.setContentHandler(handler); 126 parser.setErrorHandler(handler); 127 parser.parse(new InputSource (in)); 128 } 129 130 132 133 private class RootHandler extends DefaultHandler { 134 135 141 public void startElement( 142 String namespaceURI, 143 String localName, 144 String qName, 145 Attributes atts) throws SAXException { 146 if (localName.equals("driver")) { 147 new DriverHandler(parser, this).init(localName, atts); 148 } 149 else { 150 logger.info("<driver> must be the root element. <" 151 + localName 152 + "> is unexpected."); 153 throw new SAXException ("Config file is not of expected XML type. '" 154 + localName 155 + "' unexpected."); 156 } 157 } 158 } 159 160 161 private class DriverHandler extends AbstractHandler { 162 163 public DriverHandler(XMLReader parser, ContentHandler parentHandler) { 164 super(parser, parentHandler); 165 } 166 167 public void init(String name, Attributes attrs) { 168 String className = attrs.getValue("", "class"); 169 logger.info("loading driver " + className); 170 driverInfo = new DataSourceInfo(); 171 driverInfo.setJdbcDriver(className); 172 } 173 174 180 public void startElement( 181 String namespaceURI, 182 String localName, 183 String qName, 184 Attributes atts) throws SAXException { 185 if (localName.equals("login")) { 186 new LoginHandler(this.parser, this).init(localName, atts, driverInfo); 187 } 188 else if (localName.equals("url")) { 189 new UrlHandler(this.parser, this).init(localName, atts, driverInfo); 190 } 191 else if (localName.equals("connectionPool")) { 192 new ConnectionHandler(this.parser, this) 193 .init(localName, atts, driverInfo); 194 } 195 else { 196 logger.info("<login, url, connectionPool> are valid. <" 197 + localName 198 + "> is unexpected."); 199 throw new SAXException ("Config file is not of expected XML type"); 200 } 201 } 202 203 } 204 205 private class UrlHandler extends AbstractHandler { 206 207 213 public UrlHandler(XMLReader parser, ContentHandler parentHandler) { 214 super(parser, parentHandler); 215 } 216 217 public void init(String name, Attributes atts, DataSourceInfo driverInfo) 218 throws SAXException { 219 driverInfo.setDataSourceUrl(atts.getValue("value")); 220 if (driverInfo.getDataSourceUrl() == null) { 221 logger.info("error: <url> has no 'value'."); 222 throw new SAXException ("'<url value=' attribute is required."); 223 } 224 } 225 } 226 227 private class LoginHandler extends AbstractHandler { 228 229 235 public LoginHandler(XMLReader parser, ContentHandler parentHandler) { 236 super(parser, parentHandler); 237 } 238 239 private String passwordFromInputStream(InputStream inputStream) { 240 BufferedReader bufferedReader = null; 241 InputStreamReader inputStreamReader = null; 242 String password = null; 243 244 try { 245 inputStreamReader = new InputStreamReader (inputStream); 246 bufferedReader = new BufferedReader (inputStreamReader); 247 password = bufferedReader.readLine(); 248 } 249 catch (IOException exception) { 250 exception.printStackTrace(); 251 } 252 finally { 253 try { 254 bufferedReader.close(); 255 } 256 catch (Exception exception) { 257 } 258 259 try { 260 inputStreamReader.close(); 261 } 262 catch (Exception exception) { 263 } 264 265 try { 266 inputStream.close(); 267 } 268 catch (IOException exception) { 269 } 270 } 271 272 return password; 273 } 274 275 private String passwordFromURL(URL url) { 276 InputStream inputStream = null; 277 String password = null; 278 279 try { 280 inputStream = url.openStream(); 281 password = passwordFromInputStream(inputStream); 282 } 283 catch (IOException exception) { 284 exception.printStackTrace(); 287 } 288 289 return password; 290 } 291 292 public void init(String name, Attributes atts, DataSourceInfo driverInfo) { 293 logger.info("loading user name and password."); 294 295 String encoderClass = atts.getValue("encoderClass"); 296 String encoderSalt = atts.getValue("encoderSalt"); 297 String password = atts.getValue("password"); 298 String passwordLocation = atts.getValue("passwordLocation"); 299 String passwordSource = atts.getValue("passwordSource"); 300 String username = atts.getValue("userName"); 301 302 driverInfo.setPasswordEncoderClass(encoderClass); 303 driverInfo.setPasswordEncoderSalt(encoderSalt); 304 driverInfo.setPasswordLocation(passwordLocation); 305 driverInfo.setPasswordSource(passwordSource); 306 driverInfo.setUserName(username); 307 308 if (encoderSalt != null) { 311 passwordSource = passwordSource.replaceAll("\\{\\}", encoderSalt); 312 } 313 314 PasswordEncoding passwordEncoder = driverInfo.getPasswordEncoder(); 315 316 if (passwordLocation != null) { 319 if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_CLASSPATH)) { 320 URL url = parentConfiguration.getResourceLocator().findResource( 321 passwordSource); 322 323 if (url != null) 324 password = passwordFromURL(url); 325 else 326 logger.error("Could not find resource in CLASSPATH: " 327 + passwordSource); 328 } 329 else if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_URL)) { 330 try { 331 password = passwordFromURL(new URL (passwordSource)); 332 } 333 catch (MalformedURLException exception) { 334 exception.printStackTrace(); 335 } 336 } 337 else if (passwordLocation 338 .equals(DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE)) { 339 if (passwordSource != null) { 340 try { 341 Process process = Runtime.getRuntime().exec(passwordSource); 342 password = passwordFromInputStream(process.getInputStream()); 343 process.waitFor(); 344 } 345 catch (IOException exception) { 346 exception.printStackTrace(); 347 } 348 catch (InterruptedException exception) { 349 exception.printStackTrace(); 350 } 351 } 352 } 353 } 354 355 if (password != null && passwordEncoder != null) 356 driverInfo.setPassword(passwordEncoder.decodePassword( 357 password, 358 encoderSalt)); 359 } 360 } 361 362 private class ConnectionHandler extends AbstractHandler { 363 364 370 public ConnectionHandler(XMLReader parser, ContentHandler parentHandler) { 371 super(parser, parentHandler); 372 } 373 374 public void init(String name, Attributes atts, DataSourceInfo driverInfo) 375 throws SAXException { 376 try { 377 String min = atts.getValue("min"); 378 if (min != null) 379 driverInfo.setMinConnections(Integer.parseInt(min)); 380 381 String max = atts.getValue("max"); 382 if (max != null) 383 driverInfo.setMaxConnections(Integer.parseInt(max)); 384 } 385 catch (NumberFormatException nfex) { 386 logger.info("Error loading numeric attribute", nfex); 387 throw new SAXException ("Error reading numeric attribute.", nfex); 388 } 389 } 390 } 391 } 392 | Popular Tags |