import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NameNotFoundException;
import javax.sql.DataSource;
public class DataSourceImpl extends UnicastRemoteObject implements DataSource, DataPool{
private ConnectionParam connParam = null ;
private List<_Connection> conns = new ArrayList<_Connection>() ;
private int connectionCount = 0 ;
public DataSourceImpl(ConnectionParam connParam) throws RemoteException{
this.connParam = connParam;
}
public DataSourceImpl() throws RemoteException{
System.out.println("new !");
}
public void initConnection(){
connParam.setDriver("com.mysql.jdbc.Driver") ;
try {
Class.forName(connParam.getDriver());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
connParam.setMaxConnection(10);
connParam.setMinConnection(0);
connParam.setUrl("jdbc:mysql://localhost:3306/test") ;
}
public Connection getConnection() throws SQLException
{
//首先从连接池中找出空闲的对象
Connection conn = getFreeConnection(0);
if(conn == null){
//判断是否超过最大连接数,如果超过最大连接数
//则等待一定时间查看是否有空闲连接,否则抛出异常告诉用户无可用连接
if(getConnectionCount() >= connParam.getMaxConnection()){
conn = getFreeConnection(connParam.getWaitTime());
}
else{//没有超过连接数,重新获取一个数据库的连接
connParam.setUser("root");
connParam.setPassword("cpc");
// System.out.println(connParam.getUrl());
Connection conn2 = DriverManager.getConnection(connParam.getUrl(),
"root", "cpc");
//代理将要返回的连接对象
_Connection _conn = new _Connection(conn2,true);
synchronized(conns){
conns.add(_conn);
}
conn = _conn.getConnection();
}
}
connectionCount++ ;
return conn;
}
private int getConnectionCount() {
return connectionCount;
}
protected synchronized Connection getFreeConnection(long nTimeout)
throws SQLException
{
Connection conn = null;
Iterator iter = conns.iterator();
while(iter.hasNext()){
_Connection _conn = (_Connection)iter.next();
if(!_conn.isInUse()){
conn = _conn.getConnection();
_conn.setInUse(true);
break;
}
}
if(conn == null && nTimeout > 0){
//等待nTimeout毫秒以便看是否有空闲连接
try{
Thread.sleep(nTimeout);
}catch(Exception e){}
conn = getFreeConnection(0);
if(conn == null)
throw new SQLException("没有可用的数据库连接");
}
return conn;
}
/* (non-Javadoc)
* @see poolInOther.DataSource#customerCome()
*/
/* (non-Javadoc)
* @see poolInOther.DataPool#customerCome()
*/
public void customerCome() throws RemoteException{
System.out.println("a customer come");
ConnectionParam cp = new ConnectionParam();
DataSource ds = null ;
try {
ds = ConnectionFactory.bind("mysql", cp);
} catch (NameAlreadyBoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
try {
Connection con = ConnectionFactory.lookup("mysql").getConnection();
System.out.println(con);
} catch (Exception e) {
e.printStackTrace();
}
}
public void customerOut() throws RemoteException {
// TODO Auto-generated method stub
try {
System.out.println("customer out");
((DataSourceImpl)(ConnectionFactory.lookup("mysql"))).close();
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public PrintWriter getLogWriter() throws SQLException {
return null;
}
public int getLoginTimeout() throws SQLException {
return 0;
}
public void setLogWriter(PrintWriter arg0) throws SQLException {
}
public void setLoginTimeout(int arg0) throws SQLException {
}
public boolean isWrapperFor(Class<?> arg0) throws SQLException {
return false;
}
public <T> T unwrap(Class<T> arg0) throws SQLException {
return null;
}
class _Connection implements InvocationHandler
{
private final static String CLOSE_METHOD_NAME = "close";
private Connection conn = null;
//数据库的忙状态
private boolean inUse = false;
//用户最后一次访问该连接方法的时间
private long lastAccessTime = System.currentTimeMillis();
_Connection(Connection conn, boolean inUse){
this.conn = conn;
this.inUse = inUse;
}
/**
* Returns the conn.
* @return Connection
*/
public Connection getConnection() {
//返回数据库连接conn的接管类,以便截住close方法
// System.out.println(Proxy.newProxyInstance(
// conn.getClass().getClassLoader(),
// conn.getClass().getInterfaces(),this));
Connection conn2 = (Connection)Proxy.newProxyInstance(
conn.getClass().getClassLoader(),
conn.getClass().getInterfaces(),this);
return conn2;
}
/**
* 该方法真正的关闭了数据库的连接
* @throws SQLException
*/
void close() throws SQLException{
//由于类属性conn是没有被接管的连接,因此一旦调用close方法后就直接关闭连接
connectionCount-- ;
conn.close();
}
/**
* Returns the inUse.
* @return boolean
*/
public boolean isInUse() {
return inUse;
}
/**
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object)
*/
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable
{
Object obj = null;
//判断是否调用了close的方法,如果调用close方法则把连接置为无用状态
if(CLOSE_METHOD_NAME.equals(m.getName()))
setInUse(false);
else
obj = m.invoke(conn, args);
//设置最后一次访问时间,以便及时清除超时的连接
lastAccessTime = System.currentTimeMillis();
return obj;
}
/**
* Returns the lastAccessTime.
* @return long
*/
public long getLastAccessTime() {
return lastAccessTime;
}
/**
* Sets the inUse.
* @param inUse The inUse to set
*/
public void setInUse(boolean inUse) {
this.inUse = inUse;
}
}
public void stop() {
}
public int close() throws SQLException
{
int cc = 0;
SQLException excp = null;
Iterator iter = conns.iterator();
while(iter.hasNext()){
try{
_Connection con = (_Connection)iter.next();
con.close();
con.setInUse(false);
cc ++;
}catch(Exception e){
if(e instanceof SQLException)
excp = (SQLException)e;
}
}
if(excp != null)
throw excp;
return cc;
}
@Override
public Connection getConnection(String username, String password)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
}