001/* 002 * JKNIV, whinstone one contract to access your database. 003 * 004 * Copyright (C) 2017, the original author or authors. 005 * 006 * This library 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 2.1 of the License. 010 * 011 * This library 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 this library; if not, write to the Free Software Foundation, Inc., 018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 019 */ 020package net.sf.jkniv.whinstone.jdbc; 021 022import java.lang.reflect.Method; 023import java.sql.Connection; 024import java.sql.SQLException; 025 026import javax.sql.DataSource; 027 028import net.sf.jkniv.reflect.beans.ObjectProxy; 029import net.sf.jkniv.reflect.beans.ObjectProxyFactory; 030import net.sf.jkniv.sqlegance.RepositoryException; 031import net.sf.jkniv.sqlegance.transaction.Isolation; 032import net.sf.jkniv.whinstone.ConnectionAdapter; 033 034public class SpringDataSourceAdapter extends AbstractJdbcAdapter 035{ 036 private static final String SPRING_TRANSACTIONAWEREDATASOURCE_PROXY = "org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"; 037 private static final String SPRING_DATASOURCE_UTILS = "org.springframework.jdbc.datasource.DataSourceUtils"; 038 private DataSource dataSourceTarget; 039 private ObjectProxy<?> transactionAwareDataSourceProxy; 040 private Isolation defaultIsolation; 041 //TransactionAwareDataSourceProxy dsProxy; 042 043 public SpringDataSourceAdapter(DataSource ds, String contextName)//DataSource dataSource, Isolation defaultIsolation, String name) 044 { 045 super(contextName); 046 this.defaultIsolation = Isolation.DEFAULT; 047 this.dataSourceTarget = ds; 048 //this.dsProxy = new TransactionAwareDataSourceProxy(ds); 049 050 this.transactionAwareDataSourceProxy = ObjectProxyFactory 051 .of(classForName(SPRING_TRANSACTIONAWEREDATASOURCE_PROXY)); 052 this.transactionAwareDataSourceProxy.setConstructorArgs(dataSourceTarget); 053 this.transactionAwareDataSourceProxy.newInstance(); 054 } 055 056 public ConnectionAdapter open() 057 { 058 return open(defaultIsolation); 059 } 060 061 public ConnectionAdapter open(Isolation isolation) 062 { 063 ConnectionAdapter adapter = null; 064 try 065 { 066 LOG.debug("Getting Connection from Spring TransactionAwareDataSourceProxy class"); 067 Connection conn = (Connection) this.transactionAwareDataSourceProxy.invoke("getConnection"); 068 conn.setAutoCommit(false); 069 adapter = new JdbcConnectionAdapter(contextName, conn, this.handlerException); 070 } 071 catch (SQLException e) 072 { 073 handlerException.handle(e, "SEVERE FAIL, cannot get database connection datasource with Reason: " + e.getMessage()); 074 } 075 return adapter; 076 } 077 078 @Override 079 public void close(ConnectionAdapter conn) 080 { 081 LOG.debug("Release Connection [{}] from Spring DataSourceProxy", conn); 082 doReleaseConnection(conn); 083 } 084 085 private void doReleaseConnection(ConnectionAdapter conn) 086 { 087 Class<?>[] types = 088 { Connection.class, DataSource.class }; 089 Method m; 090 try 091 { 092 //DataSourceUtils.doReleaseConnection(conn, dsProxy.getTargetDataSource()); 093 DataSource dataSourceTarget = null; 094 m = classForName(SPRING_DATASOURCE_UTILS).getDeclaredMethod("doReleaseConnection", types); 095 m.invoke(null, new Object[] 096 { (Connection)conn.unwrap(), dataSourceTarget }); 097 } 098 catch (Exception e) 099 // TODO design exception IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException 100 { 101 handlerException.handle(e, "Cannot invoke [doReleaseConnection] from " + SPRING_DATASOURCE_UTILS + " class"); 102 } 103 } 104 105 private Class<?> classForName(String name) 106 { 107 try 108 { 109 return Class.forName(name); 110 } 111 catch (ClassNotFoundException e) 112 { 113 throw new RepositoryException("Cannot returns the Class object associated with the class [" + name + "]", 114 e); 115 } 116 } 117}