1 21 package com.jaspersoft.jasperserver.api.engine.jasperreports.service.impl; 22 23 import java.util.ArrayList ; 24 import java.util.HashMap ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.Map ; 28 29 import javax.sql.DataSource ; 30 31 import org.apache.commons.logging.Log; 32 import org.apache.commons.logging.LogFactory; 33 34 import com.jaspersoft.jasperserver.api.JSException; 35 import com.jaspersoft.jasperserver.api.metadata.jasperreports.domain.JdbcReportDataSource; 36 import com.jaspersoft.jasperserver.api.metadata.jasperreports.domain.ReportDataSource; 37 import com.jaspersoft.jasperserver.api.metadata.jasperreports.service.ReportDataSourceService; 38 import com.jaspersoft.jasperserver.api.metadata.jasperreports.service.ReportDataSourceServiceFactory; 39 40 44 public class JdbcReportDataSourceServiceFactory implements ReportDataSourceServiceFactory { 45 46 private static final Log log = LogFactory.getLog(JdbcReportDataSourceServiceFactory.class); 47 48 protected static class PooledDataSourcesCache { 49 protected static class DataSourceEntry { 50 final Object key; 51 final PooledDataSource ds; 52 DataSourceEntry next, prev; 53 long lastAccess; 54 55 public DataSourceEntry(Object key, PooledDataSource ds) { 56 this.key = key; 57 this.ds = ds; 58 } 59 60 public void access(long now) { 61 lastAccess = now; 62 } 63 } 64 65 final Map cache; 66 DataSourceEntry first, last; 67 68 public PooledDataSourcesCache() { 69 cache = new HashMap (); 70 first = last = null; 71 } 72 73 public PooledDataSource get(Object key, long now) { 74 DataSourceEntry entry = (DataSourceEntry) cache.get(key); 75 76 if (entry == null) { 77 return null; 78 } 79 80 moveFirst(entry); 81 entry.access(now); 82 return entry.ds; 83 } 84 85 private void moveFirst(DataSourceEntry entry) { 86 entry.next = first; 87 entry.prev = null; 88 if (first != null) { 89 first.prev = entry; 90 } 91 first = entry; 92 if (last == null) { 93 last = entry; 94 } 95 } 96 97 public void put(Object key, PooledDataSource ds, long now) { 98 DataSourceEntry entry = new DataSourceEntry(key, ds); 99 moveFirst(entry); 100 entry.access(now); 101 cache.put(key, entry); 102 } 103 104 public List removeExpired(long now, int timeout) { 105 List expired = new ArrayList (); 106 DataSourceEntry entry = last; 107 long expTime = now - timeout * 1000; 108 while (entry != null && entry.lastAccess < expTime) { 109 expired.add(entry.ds); 110 remove(entry); 111 entry = entry.prev; 112 } 113 return expired; 114 } 115 116 protected void remove(DataSourceEntry entry) { 117 cache.remove(entry.key); 118 if (entry.prev != null) { 119 entry.prev.next = entry.next; 120 } 121 if (entry.next != null) { 122 entry.next.prev = entry.prev; 123 } 124 if (first == entry) { 125 first = entry.next; 126 } 127 if (last == entry) { 128 last = entry.prev; 129 } 130 } 131 } 132 133 private PooledJdbcDataSourceFactory pooledJdbcDataSourceFactory; 134 private PooledDataSourcesCache poolDataSources; 135 private int poolTimeout; 136 137 public JdbcReportDataSourceServiceFactory () { 138 poolDataSources = new PooledDataSourcesCache(); 139 } 140 141 public ReportDataSourceService createService(ReportDataSource reportDataSource) { 142 if (!(reportDataSource instanceof JdbcReportDataSource)) { 143 throw new JSException("Invalid JDBC data source. Was: " + reportDataSource.getClass()); 144 } 145 JdbcReportDataSource jdbcDataSource = (JdbcReportDataSource) reportDataSource; 146 147 DataSource dataSource = getPoolDataSource(jdbcDataSource.getDriverClass(), jdbcDataSource.getConnectionUrl(), jdbcDataSource.getUsername(), jdbcDataSource.getPassword()); 148 return new JdbcDataSourceService(dataSource); 149 } 150 151 protected DataSource getPoolDataSource(String driverClass, String url, String username, String password) { 152 Object poolKey = createJdbcPoolKey(driverClass, url, username, password); 153 PooledDataSource dataSource; 154 List expired = null; 155 long now = System.currentTimeMillis(); 156 synchronized (poolDataSources) { 157 dataSource = poolDataSources.get(poolKey, now); 158 if (dataSource == null) { 159 if (log.isDebugEnabled()) { 160 log.debug("Creating connection pool for driver=\"" + driverClass + "\", url=\"" + 161 url + "\", username=\"" + username + "\"."); 162 } 163 dataSource = pooledJdbcDataSourceFactory.createPooledDataSource(driverClass, url, username, password); 164 poolDataSources.put(poolKey, dataSource, now); 165 } 166 167 if (getPoolTimeout() > 0) { 168 expired = poolDataSources.removeExpired(now, getPoolTimeout()); 169 } 170 } 171 172 if (expired != null && !expired.isEmpty()) { 173 for (Iterator it = expired.iterator(); it.hasNext();) { 174 PooledDataSource ds = (PooledDataSource) it.next(); 175 try { 176 ds.release(); 177 } catch (Exception e) { 178 log.error("Error while releasing connection pool.", e); 179 } 181 } 182 } 183 184 return dataSource.getDataSource(); 185 } 186 187 public PooledJdbcDataSourceFactory getPooledJdbcDataSourceFactory() { 188 return pooledJdbcDataSourceFactory; 189 } 190 191 public void setPooledJdbcDataSourceFactory( 192 PooledJdbcDataSourceFactory jdbcDataSourceFactory) { 193 this.pooledJdbcDataSourceFactory = jdbcDataSourceFactory; 194 } 195 196 protected Object createJdbcPoolKey(String driverClass, 197 String url, String username, String password) { 198 return new JdbcPoolKey(driverClass, url, username, password); 199 } 200 201 protected static class JdbcPoolKey { 202 private final String driverClass; 203 private final String url; 204 private final String username; 205 private final String password; 206 private final int hash; 207 208 public JdbcPoolKey(String driverClass, String url, String username, 209 String password) { 210 this.driverClass = driverClass; 211 this.url = url; 212 this.username = username; 213 this.password = password; 214 215 int hashCode = 559; 216 if (driverClass != null) { 217 hashCode += driverClass.hashCode(); 218 } 219 hashCode *= 43; 220 if (url != null) { 221 hashCode += url.hashCode(); 222 } 223 hashCode *= 43; 224 if (username != null) { 225 hashCode += username.hashCode(); 226 } 227 hashCode *= 43; 228 if (password != null) { 229 hashCode += password.hashCode(); 230 } 231 232 hash = hashCode; 233 } 234 235 public boolean equals(Object obj) { 236 if (!(obj instanceof JdbcPoolKey)) { 237 return false; 238 } 239 if (this == obj) { 240 return true; 241 } 242 243 JdbcPoolKey key = (JdbcPoolKey) obj; 244 return 245 (driverClass == null ? key.driverClass == null : (key.driverClass != null && driverClass.equals(key.driverClass))) && 246 (url == null ? key.url == null : (key.url != null && url.equals(key.url))) && 247 (username == null ? key.username == null : (key.username != null && username.equals(key.username))) && 248 (password == null ? key.password == null : (key.password != null && password.equals(key.password))); 249 } 250 251 public int hashCode() { 252 return hash; 253 } 254 255 } 256 257 public int getPoolTimeout() { 258 return poolTimeout; 259 } 260 261 public void setPoolTimeout(int poolTimeout) { 262 this.poolTimeout = poolTimeout; 263 } 264 } 265 | Popular Tags |