blob: ffdcce999cd6be7a70ec3e29fda38b293db86dd3 [file] [log] [blame]
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.server.session;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Locale;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* DatabaseAdaptor
*
* Handles differences between databases.
*
* Postgres uses the getBytes and setBinaryStream methods to access
* a "bytea" datatype, which can be up to 1Gb of binary data. MySQL
* is happy to use the "blob" type and getBlob() methods instead.
*
*/
public class DatabaseAdaptor
{
final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
String _dbName;
boolean _isLower;
boolean _isUpper;
protected String _blobType; //if not set, is deduced from the type of the database at runtime
protected String _longType; //if not set, is deduced from the type of the database at runtime
private String _driverClassName;
private String _connectionUrl;
private Driver _driver;
private DataSource _datasource;
private String _jndiName;
public DatabaseAdaptor ()
{
}
public void adaptTo(DatabaseMetaData dbMeta)
throws SQLException
{
_dbName = dbMeta.getDatabaseProductName().toLowerCase(Locale.ENGLISH);
if (LOG.isDebugEnabled())
LOG.debug ("Using database {}",_dbName);
_isLower = dbMeta.storesLowerCaseIdentifiers();
_isUpper = dbMeta.storesUpperCaseIdentifiers();
}
public void setBlobType(String blobType)
{
_blobType = blobType;
}
public String getBlobType ()
{
if (_blobType != null)
return _blobType;
if (_dbName.startsWith("postgres"))
return "bytea";
return "blob";
}
public void setLongType(String longType)
{
_longType = longType;
}
public String getLongType ()
{
if (_longType != null)
return _longType;
if (_dbName == null)
throw new IllegalStateException ("DbAdaptor missing metadata");
if (_dbName.startsWith("oracle"))
return "number(20)";
return "bigint";
}
/**
* Convert a camel case identifier into either upper or lower
* depending on the way the db stores identifiers.
*
* @param identifier the raw identifier
* @return the converted identifier
*/
public String convertIdentifier (String identifier)
{
if (_dbName == null)
throw new IllegalStateException ("DbAdaptor missing metadata");
if (_isLower)
return identifier.toLowerCase(Locale.ENGLISH);
if (_isUpper)
return identifier.toUpperCase(Locale.ENGLISH);
return identifier;
}
public String getDBName ()
{
return _dbName;
}
public InputStream getBlobInputStream (ResultSet result, String columnName)
throws SQLException
{
if (_dbName == null)
throw new IllegalStateException ("DbAdaptor missing metadata");
if (_dbName.startsWith("postgres"))
{
byte[] bytes = result.getBytes(columnName);
return new ByteArrayInputStream(bytes);
}
Blob blob = result.getBlob(columnName);
return blob.getBinaryStream();
}
public boolean isEmptyStringNull ()
{
if (_dbName == null)
throw new IllegalStateException ("DbAdaptor missing metadata");
return (_dbName.startsWith("oracle"));
}
/**
* rowId is a reserved word for Oracle, so change the name of this column
* @return true if db in use is oracle
*/
public boolean isRowIdReserved ()
{
if (_dbName == null)
throw new IllegalStateException ("DbAdaptor missing metadata");
return (_dbName != null && _dbName.startsWith("oracle"));
}
/**
* Configure jdbc connection information via a jdbc Driver
*
* @param driverClassName the driver classname
* @param connectionUrl the driver connection url
*/
public void setDriverInfo (String driverClassName, String connectionUrl)
{
_driverClassName=driverClassName;
_connectionUrl=connectionUrl;
}
/**
* Configure jdbc connection information via a jdbc Driver
*
* @param driverClass the driver class
* @param connectionUrl the driver connection url
*/
public void setDriverInfo (Driver driverClass, String connectionUrl)
{
_driver=driverClass;
_connectionUrl=connectionUrl;
}
public void setDatasource (DataSource ds)
{
_datasource = ds;
}
public void setDatasourceName (String jndi)
{
_jndiName=jndi;
}
public void initialize ()
throws Exception
{
if (_datasource != null)
return; //already set up
if (_jndiName!=null)
{
InitialContext ic = new InitialContext();
_datasource = (DataSource)ic.lookup(_jndiName);
}
else if ( _driver != null && _connectionUrl != null )
{
DriverManager.registerDriver(_driver);
}
else if (_driverClassName != null && _connectionUrl != null)
{
Class.forName(_driverClassName);
}
else
{
try
{
InitialContext ic = new InitialContext();
_datasource = (DataSource)ic.lookup("jdbc/sessions"); //last ditch effort
}
catch (NamingException e)
{
throw new IllegalStateException("No database configured for sessions");
}
}
}
/**
* Get a connection from the driver or datasource.
*
* @return the connection for the datasource
* @throws SQLException if unable to get the connection
*/
protected Connection getConnection ()
throws SQLException
{
if (_datasource != null)
return _datasource.getConnection();
else
return DriverManager.getConnection(_connectionUrl);
}
}