001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2009 SonarSource SA 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.api.database; 021 022 import org.apache.commons.configuration.Configuration; 023 import org.apache.commons.lang.StringUtils; 024 025 import java.sql.Connection; 026 import java.sql.Driver; 027 import java.sql.DriverManager; 028 import java.sql.SQLException; 029 import java.util.Properties; 030 031 public class DriverDatabaseConnector extends AbstractDatabaseConnector { 032 033 private ClassLoader classloader; 034 035 public DriverDatabaseConnector(Configuration configuration) { 036 super(configuration, true); 037 this.classloader = getClass().getClassLoader(); 038 } 039 040 public DriverDatabaseConnector(Configuration configuration, ClassLoader classloader) { 041 super(configuration, true); 042 this.classloader = classloader; 043 } 044 045 public String getDriver() { 046 String driver = getConfiguration().getString(DatabaseProperties.PROP_DRIVER); 047 if (driver == null) { 048 driver = getConfiguration().getString(DatabaseProperties.PROP_DRIVER_DEPRECATED); 049 } 050 if (driver == null) { 051 driver = DatabaseProperties.PROP_DRIVER_DEFAULT_VALUE; 052 } 053 return driver; 054 } 055 056 public String getUrl() { 057 return getConfiguration().getString(DatabaseProperties.PROP_URL, DatabaseProperties.PROP_URL_DEFAULT_VALUE); 058 } 059 060 public String getUsername() { 061 String username = getConfiguration().getString(DatabaseProperties.PROP_USER); 062 if (username == null) { 063 username = getConfiguration().getString(DatabaseProperties.PROP_USER_DEPRECATED); 064 } 065 if (username == null) { 066 username = DatabaseProperties.PROP_USER_DEFAULT_VALUE; 067 } 068 return username; 069 } 070 071 public String getPassword() { 072 return getConfiguration().getString(DatabaseProperties.PROP_PASSWORD, DatabaseProperties.PROP_PASSWORD_DEFAULT_VALUE); 073 } 074 075 public Connection getConnection() throws SQLException { 076 try { 077 /* 078 The sonar batch downloads the JDBC driver in a separated classloader. 079 This is a well-know problem of java.sql.DriverManager. The workaround 080 is to use a proxy. 081 See http://stackoverflow.com/questions/288828/how-to-use-a-jdbc-driver-from-an-arbitrary-location 082 */ 083 Driver driver = (Driver)classloader.loadClass(getDriver()).newInstance(); 084 DriverManager.registerDriver(new DriverProxy(driver)); 085 086 } catch (Exception e) { 087 SQLException ex = new SQLException("SQL driver not found " + getDriver()); 088 ex.initCause(e); 089 throw ex; 090 } 091 return DriverManager.getConnection(getUrl(), getUsername(), getPassword()); 092 } 093 094 @Override 095 public void setupEntityManagerFactory(Properties factoryProps) { 096 factoryProps.put("hibernate.connection.url", getUrl()); 097 factoryProps.put("hibernate.connection.driver_class", getDriver()); 098 factoryProps.put("hibernate.connection.username", getUsername()); 099 if (StringUtils.isNotEmpty(getPassword())) { 100 factoryProps.put("hibernate.connection.password", getPassword()); 101 } 102 } 103 } 104 105 /** 106 * A Driver that stands in for another Driver. 107 * This is necessary because java.sql.DriverManager 108 * examines the Driver class class loader. 109 */ 110 final class DriverProxy implements Driver { 111 private final Driver target; 112 113 DriverProxy(java.sql.Driver target) { 114 if (target == null) { 115 throw new NullPointerException(); 116 } 117 this.target = target; 118 } 119 120 public java.sql.Driver getTarget() { 121 return target; 122 } 123 124 public boolean acceptsURL(String url) throws SQLException { 125 return target.acceptsURL(url); 126 } 127 128 public java.sql.Connection connect( 129 String url, java.util.Properties info 130 ) throws SQLException { 131 return target.connect(url, info); 132 } 133 134 public int getMajorVersion() { 135 return target.getMajorVersion(); 136 } 137 138 public int getMinorVersion() { 139 return target.getMinorVersion(); 140 } 141 142 public java.sql.DriverPropertyInfo[] getPropertyInfo( 143 String url, java.util.Properties info 144 ) throws SQLException { 145 return target.getPropertyInfo(url, info); 146 } 147 148 public boolean jdbcCompliant() { 149 return target.jdbcCompliant(); 150 } 151 152 @Override 153 public String toString() { 154 return "Proxy: " + target; 155 } 156 157 @Override 158 public int hashCode() { 159 return target.hashCode(); 160 } 161 162 @Override 163 public boolean equals(Object obj) { 164 if (!(obj instanceof DriverProxy)) { 165 return false; 166 } 167 DriverProxy other = (DriverProxy) obj; 168 return this.target.equals(other.target); 169 } 170 }