All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.adejanovski.cassandra.jdbc.CassandraDriver Maven / Gradle / Ivy

There is a newer version: 3.1.0
Show newest version
/*
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
package com.github.adejanovski.cassandra.jdbc;

import static com.github.adejanovski.cassandra.jdbc.Utils.NOT_SUPPORTED;
import static com.github.adejanovski.cassandra.jdbc.Utils.PROTOCOL;
import static com.github.adejanovski.cassandra.jdbc.Utils.TAG_PASSWORD;
import static com.github.adejanovski.cassandra.jdbc.Utils.TAG_USER;

import java.sql.*;
import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutionException;

import com.google.common.cache.*;
import com.google.common.collect.ImmutableMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The Class CassandraDriver.
 */
public class CassandraDriver implements Driver
{
    public static final int DVR_MAJOR_VERSION = 2;

    public static final int DVR_MINOR_VERSION = 1;

    public static final int DVR_PATCH_VERSION = 6;

    public static final String DVR_NAME = "Datastax JDBC Driver";

    private static final Logger logger = LoggerFactory.getLogger(CassandraDriver.class);

    static
    {
        // Register the CassandraDriver with DriverManager
        try
        {
            CassandraDriver driverInst = new CassandraDriver();
            DriverManager.registerDriver(driverInst);
        }
        catch (SQLException e)
        {
            throw new RuntimeException(e.getMessage());
        }
    }

    // Caches Sessions so that multiple CassandraConnections created with the same parameters use the same Session.
    private final LoadingCache, SessionHolder> sessionsCache = CacheBuilder.newBuilder()
        .build(new CacheLoader, SessionHolder>() {
                   @Override
                   public SessionHolder load(final Map params) throws Exception {
                       return new SessionHolder(params, sessionsCache);
                   }
               }
        );

    /**
     * Method to validate whether provided connection url matches with pattern or not.
     */
    public boolean acceptsURL(String url) throws SQLException
    {
        return url.startsWith(PROTOCOL);
    }

    /**
     * Method to return connection instance for given connection url and connection props.
     */
    public Connection connect(String url, Properties props) throws SQLException
    {
        if (acceptsURL(url))
        {
            ImmutableMap.Builder params = ImmutableMap.builder();

            Enumeration keys = props.keys();
            while (keys.hasMoreElements()) {
                String key = (String)keys.nextElement();
                params.put(key, props.getProperty(key));
            }
            params.put(SessionHolder.URL_KEY, url);

            Map cacheKey = params.build();

            try {
                while (true) {
                    // Get (or create) the corresponding Session from the cache
                    SessionHolder sessionHolder = sessionsCache.get(cacheKey);

                    if (sessionHolder.acquire())
                        return new CassandraConnection(sessionHolder);
                    // If we failed to acquire, it means we raced with the release of the last reference to the session
                    // (which also removes it from the cache).
                    // Loop to try again, that will cause the cache to create a new instance.
                }
            } catch (ExecutionException e) {
                Throwable cause = e.getCause();
                if (cause instanceof SQLException)
                    throw (SQLException)cause;
				throw new SQLNonTransientConnectionException("Unexpected error while creating connection", e);
            }
        }
		return null; // signal it is the wrong driver for this protocol:subprotocol
    }

    /**
     * Returns default major version.
     */
    public int getMajorVersion()
    {
        return DVR_MAJOR_VERSION;
    }

    /**
     * Returns default minor version.
     */
    public int getMinorVersion()
    {
        return DVR_MINOR_VERSION;
    }

    /**
     * Returns default driver property info object.
     */
    public DriverPropertyInfo[] getPropertyInfo(String url, Properties props) throws SQLException
    {
        if (props == null) props = new Properties();

        DriverPropertyInfo[] info = new DriverPropertyInfo[2];

        info[0] = new DriverPropertyInfo(TAG_USER, props.getProperty(TAG_USER));
        info[0].description = "The 'user' property";

        info[1] = new DriverPropertyInfo(TAG_PASSWORD, props.getProperty(TAG_PASSWORD));
        info[1].description = "The 'password' property";

        return info;
    }

    /**
     * Returns true, if it is jdbc compliant.
     */
    public boolean jdbcCompliant()
    {
        return false;
    }
    
    public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException
    {
    	throw new SQLFeatureNotSupportedException(String.format(NOT_SUPPORTED));
    }
}