001/*******************************************************************************
002 * Copyright (c) 2013 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     Nuxeo - initial API and implementation
011 *******************************************************************************/
012package org.nuxeo.runtime.datasource;
013
014import java.sql.Connection;
015import java.sql.SQLException;
016import java.util.HashMap;
017import java.util.Hashtable;
018import java.util.Map;
019import java.util.concurrent.locks.ReentrantReadWriteLock;
020
021import javax.naming.Context;
022import javax.naming.Name;
023import javax.naming.Reference;
024import javax.naming.spi.ObjectFactory;
025import javax.sql.DataSource;
026
027import org.nuxeo.runtime.datasource.geronimo.PooledDataSourceFactory;
028
029public class PooledDataSourceRegistry extends ReentrantReadWriteLock {
030
031    private static final long serialVersionUID = 1L;
032
033    public interface Factory extends ObjectFactory {
034
035    }
036
037    public interface PooledDataSource extends DataSource {
038        void dispose();
039
040        Connection getConnection(boolean noSharing) throws SQLException;
041    }
042
043    protected final Map<String, PooledDataSource> pools = new HashMap<>();
044
045    protected final PooledDataSourceFactory poolFactory = new org.nuxeo.runtime.datasource.geronimo.PooledDataSourceFactory();
046
047    public <T> T getPool(String name, Class<T> type) {
048        return type.cast(pools.get(name));
049    }
050
051    public DataSource getOrCreatePool(Object obj, Name objectName, Context nameCtx, Hashtable<?, ?> env) {
052        final Reference ref = (Reference) obj;
053        String dsName = (String) ref.get("name").getContent();
054        DataSource ds = pools.get(dsName);
055        if (ds != null) {
056            return ds;
057        }
058        return createPool(dsName, ref, objectName, nameCtx, env);
059    }
060
061    protected DataSource createPool(String dsName, Reference ref, Name objectName, Context nameCtx, Hashtable<?, ?> env) {
062        PooledDataSource ds;
063        try {
064            readLock().lock();
065            ds = pools.get(dsName);
066            if (ds != null) {
067                return ds;
068            }
069            ds = (PooledDataSource) poolFactory.getObjectInstance(ref, objectName, nameCtx, env);
070            pools.put(dsName, ds);
071        } finally {
072            readLock().unlock();
073        }
074        return ds;
075    }
076
077    protected void clearPool(String name) {
078        PooledDataSource ds = pools.remove(name);
079        if (ds != null) {
080            ds.dispose();
081        }
082    }
083
084    public void createAlias(String name, PooledDataSource pool) {
085        pools.put(name, pool);
086    }
087
088}