/* * Copyright (c) 2004, 2005, 2006 TADA AB - Taby Sweden * Distributed under the terms shown in the file COPYRIGHT * found in the root directory of this distribution or at * http://eng.tada.se/osprojects/COPYRIGHT.html */ package org.postgresql.pljava.internal; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.sql.SQLException; import java.util.IdentityHashMap; import org.postgresql.pljava.ObjectPool; import org.postgresql.pljava.PooledObject; class ObjectPoolImpl implements ObjectPool { /** * An InstanceHandle is a link in a single linked list that * holds on to a ResultSetProvider. */ private static class PooledObjectHandle { private PooledObject m_instance; private PooledObjectHandle m_next; } private static Class[] s_ctorSignature = { ObjectPool.class }; private static PooledObjectHandle s_handlePool; private static final IdentityHashMap s_poolCache = new IdentityHashMap(); private final Constructor m_ctor; private PooledObjectHandle m_providerPool; private ObjectPoolImpl(Class c) { if(!PooledObject.class.isAssignableFrom(c)) throw new IllegalArgumentException("Class " + c + " does not implement the " + PooledObject.class + " interface"); try { m_ctor = c.getConstructor(s_ctorSignature); } catch(SecurityException e) { throw new RuntimeException(e); } catch(NoSuchMethodException e) { throw new IllegalArgumentException("Unable to locate constructor " + c + "(ObjectPool)"); } } /** * Obtain a pool for the given class. * @param cls * @return * @throws SQLException */ public static ObjectPoolImpl getObjectPool(Class cls) { ObjectPoolImpl pool = (ObjectPoolImpl)s_poolCache.get(cls); if(pool == null) { pool = new ObjectPoolImpl(cls); s_poolCache.put(cls, pool); } return pool; } public PooledObject activateInstance() throws SQLException { PooledObject instance; PooledObjectHandle handle = m_providerPool; if(handle != null) { m_providerPool = handle.m_next; instance = handle.m_instance; // Return the handle to the unused handle pool. // handle.m_instance = null; handle.m_next = s_handlePool; s_handlePool = handle; } else { try { instance = (PooledObject)m_ctor.newInstance(new Object[] { this }); } catch(InvocationTargetException e) { Throwable t = e.getTargetException(); if(t instanceof SQLException) throw (SQLException)t; if(t instanceof RuntimeException) throw (RuntimeException)t; if(t instanceof Error) throw (Error)t; throw new SQLException(e.getMessage()); } catch(RuntimeException e) { throw e; } catch(Exception e) { throw new SQLException("Failed to create an instance of: " + m_ctor.getDeclaringClass() + " :" + e.getMessage()); } } try { instance.activate(); } catch(SQLException e) { instance.remove(); throw e; } return instance; } public void passivateInstance(PooledObject instance) throws SQLException { try { instance.passivate(); } catch(SQLException e) { instance.remove(); throw e; } // Obtain a handle from the pool of handles so that // we have something to wrap the instance in. // PooledObjectHandle handle = s_handlePool; if(handle != null) s_handlePool = handle.m_next; else handle = new PooledObjectHandle(); handle.m_instance = instance; handle.m_next = m_providerPool; m_providerPool = handle; } public void removeInstance(PooledObject instance) throws SQLException { PooledObjectHandle prev = null; for(PooledObjectHandle handle = m_providerPool; handle != null; handle = handle.m_next) { if(handle.m_instance == instance) { if(prev == null) m_providerPool = handle.m_next; else prev.m_next = handle.m_next; handle.m_instance = null; handle.m_next = s_handlePool; s_handlePool = handle; break; } } instance.remove(); } }