package org.pentaho.reporting.engine.classic.extensions.datasources.mondrian;
import java.util.Properties;
import java.util.HashMap;
import java.io.Serializable;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.DriverManager;
import javax.sql.DataSource;
import org.pentaho.reporting.libraries.base.util.LFUMap;
/**
* Mondrian uses the Identity-Hashkey for creating its cache-key. So we better return the same instance for the
* same connection information, or caching will be effectively disabled.
*
* @author Thomas Morgner.
*/
public class DriverDataSourceCache
{
private static class DriverConnectionKey implements Serializable
{
private String jdbcConnectString;
private Properties jdbcProperties;
private DriverConnectionKey(final String jdbcConnectString, final Properties jdbcProperties)
{
if (jdbcConnectString == null)
{
throw new NullPointerException();
}
if (jdbcProperties == null)
{
throw new NullPointerException();
}
this.jdbcConnectString = jdbcConnectString;
this.jdbcProperties = (Properties) jdbcProperties.clone();
}
public boolean equals(final Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
final DriverConnectionKey that = (DriverConnectionKey) o;
if (!jdbcConnectString.equals(that.jdbcConnectString))
{
return false;
}
if (!jdbcProperties.equals(that.jdbcProperties))
{
return false;
}
return true;
}
public int hashCode()
{
int result = jdbcConnectString.hashCode();
result = 31 * result + jdbcProperties.hashCode();
return result;
}
}
/**
* Implementation of {@link DataSource} which calls the good ol'
* {@link java.sql.DriverManager}.
*/
private static class DriverManagerDataSource implements DataSource
{
private String jdbcConnectString;
private PrintWriter logWriter;
private int loginTimeout;
private Properties jdbcProperties;
public DriverManagerDataSource(final String jdbcConnectString,
final Properties properties)
{
if (jdbcConnectString == null)
{
throw new NullPointerException();
}
if (properties == null)
{
throw new NullPointerException();
}
this.jdbcConnectString = jdbcConnectString;
this.jdbcProperties = (Properties) properties.clone();
}
public boolean equals(final Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
final DriverManagerDataSource that = (DriverManagerDataSource) o;
if (loginTimeout != that.loginTimeout)
{
return false;
}
if (!jdbcConnectString.equals(that.jdbcConnectString))
{
return false;
}
if (!jdbcProperties.equals(that.jdbcProperties))
{
return false;
}
if (logWriter != null ? !logWriter.equals(that.logWriter) : that.logWriter != null)
{
return false;
}
return true;
}
public int hashCode()
{
int result = jdbcConnectString.hashCode();
result = 31 * result + (logWriter != null ? logWriter.hashCode() : 0);
result = 31 * result + loginTimeout;
result = 31 * result + jdbcProperties.hashCode();
return result;
}
public Connection getConnection() throws SQLException
{
return DriverManager.getConnection(jdbcConnectString, jdbcProperties);
}
public Connection getConnection(final String username, final String password)
throws SQLException
{
final Properties temp = (Properties) jdbcProperties.clone();
temp.put("user", username);
temp.put("password", password);
return java.sql.DriverManager.getConnection(jdbcConnectString, temp);
}
public PrintWriter getLogWriter() throws SQLException
{
return logWriter;
}
public void setLogWriter(final PrintWriter out) throws SQLException
{
logWriter = out;
}
public void setLoginTimeout(final int seconds) throws SQLException
{
loginTimeout = seconds;
}
public int getLoginTimeout() throws SQLException
{
return loginTimeout;
}
public boolean isWrapperFor(Class c)
{
return false;
}
public <T> T unwrap (Class<T> c) throws SQLException
{
throw new SQLException("This class cannot be unwrapped.");
}
}
private static LFUMap cache;
private DriverDataSourceCache()
{
}
public static synchronized DataSource createDataSource(final String jdbcUrl, final Properties properties)
{
if (cache == null)
{
cache = new LFUMap(20);
}
final DriverConnectionKey key = new DriverConnectionKey(jdbcUrl, properties);
final Object o = cache.get(key);
if (o instanceof DataSource)
{
return (DataSource) o;
}
final DriverManagerDataSource managerDataSource = new DriverManagerDataSource(jdbcUrl, properties);
cache.put(key, managerDataSource);
return managerDataSource;
}
}