-
-
Save tux19/4ea019f7ef333f0036ef3a8cf4b6019e to your computer and use it in GitHub Desktop.
Custom HostConnectionAccessor for Pocketknife QueryDSL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.reflect.Field | |
import java.sql.Connection | |
import com.atlassian.activeobjects.external.ActiveObjects | |
import com.atlassian.activeobjects.spi.{DatabaseType, TenantAwareDataSourceProvider} | |
import com.atlassian.sal.api.rdbms.ConnectionCallback | |
import com.atlassian.tenancy.api.TenantAccessor | |
import javax.inject.{Inject, Named} | |
import javax.sql.DataSource | |
import org.osgi.framework.FrameworkUtil | |
import org.springframework.context.annotation.Primary | |
@Primary | |
@Named | |
class HostConnectionAccessor @Inject()() extends Logging{ | |
//todo handle such situations better, on plugin start the values should never be null | |
protected val bundleContext = scala.Option(FrameworkUtil.getBundle(classOf[ActiveObjects])).map(_.getBundleContext).orNull | |
protected val tenantAccessor = scala.Option(bundleContext).map( | |
_.getService(bundleContext | |
.getServiceReference(classOf[TenantAccessor].getName)) | |
.asInstanceOf[TenantAccessor]).orNull | |
protected val dataSourceProvider = scala.Option(bundleContext).map( | |
_.getService(bundleContext | |
.getServiceReference(classOf[TenantAwareDataSourceProvider].getName)) | |
.asInstanceOf[TenantAwareDataSourceProvider]).orNull | |
def getSchemaName: Option[String] = { | |
val tenant = tenantAccessor.getAvailableTenants.iterator().next() | |
val src = dataSourceProvider.getDataSource(tenant) | |
val con = src.getConnection | |
try { | |
dataSourceProvider.getDatabaseType(tenant) match { | |
case DatabaseType.H2 => | |
// nasty get internal session of connection object via reflection | |
val metadataCon = con.getMetaData.getConnection | |
try { | |
extractSchemaNameFromConnection(metadataCon) | |
} catch { | |
case e: NoSuchFieldException => | |
// BB 7.4 has no session on metadataCon, but a delegate field with the session. | |
val delegateField = getField(metadataCon.getClass,"delegate") | |
delegateField.setAccessible(true) | |
val delegateCon = delegateField.get(metadataCon).asInstanceOf[Connection] | |
extractSchemaNameFromConnection(delegateCon) | |
} | |
case DatabaseType.POSTGRESQL => Option(con.getSchema) | |
case DatabaseType.MYSQL => Option(con.getCatalog) | |
case DatabaseType.ORACLE => Option(con.getMetaData.getUserName) | |
case _ => Option(con.getSchema) | |
} | |
} finally { | |
con.close() | |
} | |
} | |
def getDataSource: DataSource = dataSourceProvider.getDataSource(tenantAccessor.getAvailableTenants.iterator().next()) | |
def getDatabaseType: DatabaseType = dataSourceProvider.getDatabaseType(tenantAccessor.getAvailableTenants.iterator().next()) | |
def execute[A](b: Boolean, b1: Boolean, connectionCallback: ConnectionCallback[A]): A = throw new RuntimeException | |
private def extractSchemaNameFromConnection(con: Connection) = { | |
val sessionField = con.getClass.getDeclaredField("session") | |
sessionField.setAccessible(true) | |
val session = sessionField.get(con) | |
val schemaField = session.getClass.getDeclaredField("currentSchemaName") | |
schemaField.setAccessible(true) | |
Option(schemaField.get(session).asInstanceOf[String]) | |
} | |
/** | |
* Returns the first {@link Field} in the hierarchy for the specified name | |
*/ | |
def getField(clazz: Class[_], name: String): Field = { | |
var field: Field = null | |
var currentClazz = clazz | |
while ( { | |
currentClazz != null && field == null | |
}) { | |
try { | |
field = currentClazz.getDeclaredField(name) | |
} | |
catch { | |
case e: Exception => | |
} | |
currentClazz = currentClazz.getSuperclass | |
} | |
field | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment