1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.synchronoss.cpo.jdbc;
22
23 import java.lang.reflect.InvocationTargetException;
24 import java.lang.reflect.Method;
25 import java.sql.Connection;
26 import java.sql.SQLException;
27 import java.util.LinkedList;
28 import java.util.Queue;
29 import java.util.SortedMap;
30 import javax.sql.*;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.synchronoss.cpo.CpoException;
34 import org.synchronoss.cpo.helper.CpoClassLoader;
35 import org.synchronoss.cpo.helper.ExceptionHelper;
36
37
38
39
40
41
42
43
44 public class ClassDataSourceInfo extends AbstractDataSource implements ConnectionEventListener {
45
46 private Logger logger = LoggerFactory.getLogger(this.getClass());
47 private ConnectionPoolDataSource poolDataSource = null;
48 private String className = null;
49 private SortedMap<String, String> properties = null;
50
51 final private Object LOCK = new Object();
52 private Queue<PooledConnection> freeConnections = new LinkedList<PooledConnection>();
53 private Queue<PooledConnection> usedConnections = new LinkedList<PooledConnection>();
54
55
56
57
58
59
60
61 public ClassDataSourceInfo(String className, SortedMap<String, String> properties) throws CpoException {
62 super(className, properties);
63 this.className=className;
64 this.properties=properties;
65 }
66
67 @Override
68 public Connection getConnection() throws SQLException {
69 return getPooledConnection();
70 }
71
72 private Connection getPooledConnection() throws SQLException {
73 PooledConnection pooledConn;
74 synchronized (LOCK) {
75 if (!freeConnections.isEmpty()) {
76 pooledConn = freeConnections.poll();
77 } else {
78 pooledConn = poolDataSource.getPooledConnection();
79 pooledConn.addConnectionEventListener(this);
80 }
81 usedConnections.add(pooledConn);
82 }
83 return pooledConn.getConnection();
84 }
85
86 @Override
87 public synchronized String toString() {
88 StringBuilder info = new StringBuilder();
89 info.append("JdbcDataSource(");
90 info.append(getDataSourceName());
91 info.append(")");
92 return (info.toString());
93 }
94
95 @Override
96 protected DataSource createDataSource() throws CpoException {
97 DataSource dataSource = null;
98 try {
99 Class dsClass = CpoClassLoader.forName(className);
100 CommonDataSource ds = (CommonDataSource) dsClass.newInstance();
101
102 if (ds instanceof ConnectionPoolDataSource) {
103 this.poolDataSource = (ConnectionPoolDataSource) ds;
104 dataSource = this;
105 } else if (ds instanceof DataSource) {
106 dataSource = (DataSource) ds;
107 } else {
108 throw new CpoException(className + "is not a DataSource");
109 }
110 if (properties !=null)
111 setClassProperties(ds,properties);
112 } catch (ClassNotFoundException cnfe) {
113 throw new CpoException("Could Not Find Class: " + className, cnfe);
114 } catch (InstantiationException ie) {
115 throw new CpoException("Could Not Instantiate Class: " + className + ":" + ExceptionHelper.getLocalizedMessage(ie));
116 } catch (IllegalAccessException iae) {
117 throw new CpoException("Could Not Access Class: " + className, iae);
118 }
119
120 return dataSource;
121 }
122
123 @Override
124 public void connectionClosed(ConnectionEvent ce) {
125 synchronized (LOCK) {
126 PooledConnection pc = (PooledConnection) ce.getSource();
127 if (usedConnections.remove(pc)) {
128 freeConnections.add(pc);
129 }
130 }
131 }
132
133 @Override
134 public void connectionErrorOccurred(ConnectionEvent ce) {
135 synchronized (LOCK) {
136 PooledConnection pc = (PooledConnection) ce.getSource();
137 if (!usedConnections.remove(pc)) {
138
139 freeConnections.remove(pc);
140 }
141 }
142 }
143
144 @Override
145 protected void finalize() throws Throwable {
146 super.finalize();
147 for (PooledConnection pc : freeConnections) {
148 pc.removeConnectionEventListener(this);
149 try {
150 pc.close();
151 } catch (SQLException se) {
152 }
153 }
154 for (PooledConnection pc : usedConnections) {
155 pc.removeConnectionEventListener(this);
156 try {
157 pc.close();
158 } catch (SQLException se) {
159 }
160 }
161 }
162
163 private void setClassProperties(CommonDataSource ds, SortedMap<String, String> properties) {
164 for (String key : properties.keySet()) {
165 setObjectProperty(ds, key, properties.get(key));
166 }
167 }
168
169 private void setObjectProperty(Object obj, String key, String value) {
170 String methodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1);
171 logger.debug("Calling "+methodName+"("+value+")");
172 try {
173 Method setter = obj.getClass().getMethod(methodName, String.class);
174 setter.invoke(obj, value);
175 } catch (NoSuchMethodException nsme) {
176 logger.error("=========>>> Could not find setter Method:" + methodName + " for property:" + key + " please check the java docs for " + obj.getClass().getName());
177 } catch (InvocationTargetException ite) {
178 logger.error("Error Invoking setter Method:" + methodName, ite);
179 } catch (IllegalAccessException iae) {
180 logger.error("Error accessing setter Method:" + methodName, iae);
181 }
182 }
183 }