/*
* Copyright (c) 2004, 2005, 2006 TADA AB - Taby Sweden
* Distributed under the terms shown in the file COPYRIGHT
* found in the root folder of this project or at
* http://eng.tada.se/osprojects/COPYRIGHT.html
*/
package org.postgresql.pljava.internal;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import org.postgresql.pljava.ObjectPool;
import org.postgresql.pljava.SavepointListener;
import org.postgresql.pljava.TransactionListener;
import org.postgresql.pljava.jdbc.SQLUtils;
/**
* An instance of this interface reflects the current session. The attribute
* store is transactional.
*
* @author Thomas Hallgren
*/
public class Session implements org.postgresql.pljava.Session
{
private final TransactionalMap m_attributes = new TransactionalMap(new HashMap());
/**
* Adds the specified listener to the list of listeners that will
* receive transactional events.
*/
public void addTransactionListener(TransactionListener listener)
{
XactListener.addListener(listener);
}
/**
* Adds the specified listener to the list of listeners that will
* receive savepoint events.
*/
public void addSavepointListener(SavepointListener listener)
{
SubXactListener.addListener(listener);
}
public Object getAttribute(String attributeName)
{
return m_attributes.get(attributeName);
}
public ObjectPool getObjectPool(Class cls)
{
return ObjectPoolImpl.getObjectPool(cls);
}
@Override
public String getUserName()
{
return AclId.getUser().getName();
}
@Override
public String getOuterUserName()
{
return AclId.getOuterUser().getName();
}
@Override
public String getSessionUserName()
{
return getOuterUserName();
}
public void removeAttribute(String attributeName)
{
m_attributes.remove(attributeName);
}
public void setAttribute(String attributeName, Object value)
{
m_attributes.put(attributeName, value);
}
/**
* Removes the specified listener from the list of listeners that will
* receive transactional events.
*/
public void removeTransactionListener(TransactionListener listener)
{
XactListener.removeListener(listener);
}
/**
* Removes the specified listener from the list of listeners that will
* receive savepoint events.
*/
public void removeSavepointListener(SavepointListener listener)
{
SubXactListener.removeListener(listener);
}
@Override
public void executeAsSessionUser(Connection conn, String statement)
throws SQLException
{
executeAsOuterUser(conn, statement);
}
@Override
public void executeAsOuterUser(Connection conn, String statement)
throws SQLException
{
Statement stmt = conn.createStatement();
synchronized(Backend.THREADLOCK)
{
ResultSet rs = null;
AclId outerUser = AclId.getOuterUser();
AclId effectiveUser = AclId.getUser();
boolean wasLocalChange = false;
boolean changeSucceeded = false;
try
{
wasLocalChange = _setUser(outerUser, true);
changeSucceeded = true;
if(stmt.execute(statement))
{
rs = stmt.getResultSet();
rs.next();
}
}
finally
{
SQLUtils.close(rs);
SQLUtils.close(stmt);
if ( changeSucceeded )
_setUser(effectiveUser, wasLocalChange);
}
}
}
/**
* Return current_schema() as the outer user would see it.
* Currently used only in Commands.java. Not made visible API yet
* because there <em>has</em> to be a more general way to do this.
*/
public String getOuterUserSchema()
throws SQLException
{
Statement stmt = SQLUtils.getDefaultConnection().createStatement();
synchronized(Backend.THREADLOCK)
{
ResultSet rs = null;
AclId sessionUser = AclId.getSessionUser();
AclId effectiveUser = AclId.getUser();
boolean wasLocalChange = false;
boolean changeSucceeded = false;
try
{
wasLocalChange = _setUser(sessionUser, true);
changeSucceeded = true;
rs = stmt.executeQuery("SELECT current_schema()");
if ( rs.next() )
return rs.getString(1);
throw new SQLException("Unable to obtain current schema");
}
finally
{
SQLUtils.close(rs);
SQLUtils.close(stmt);
if ( changeSucceeded )
_setUser(effectiveUser, wasLocalChange);
}
}
}
/**
* Called from native code when the JVM is instantiated.
*/
static long init()
throws SQLException
{
ELogHandler.init();
// Should be replace with a Thread.getId() once we abandon
// Java 1.4
//
return System.identityHashCode(Thread.currentThread());
}
private static native boolean _setUser(AclId userId, boolean isLocalChange);
}