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

com.m11n.jdbc.ssh.SshDriver Maven / Gradle / Ivy

package com.m11n.jdbc.ssh;

import java.net.MalformedURLException;
import java.net.URL;
import java.sql.*;
import java.util.Enumeration;
import java.util.Properties;
import java.util.logging.Logger;

import static com.m11n.jdbc.ssh.SshConfiguration.*;

public class SshDriver implements Driver {
    private static final int VERSION_MAJOR = 1;
    private static final int VERSION_MINOR = 0;

    private SshTunnel tunnel;

    public SshDriver() throws SQLException {
    }

    static
    {
        try
        {
            java.sql.DriverManager.registerDriver(new SshDriver());
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public boolean acceptsURL(String url) throws SQLException {
        return (url != null && url.startsWith(DRIVER_PREFIX));
    }

    private String extractUrl(String url) {
        return url.startsWith(DRIVER_PREFIX) ? url.replace("ssh:", "") : url;
    }

    @Override
    public Connection connect(String url, Properties info) throws SQLException {
        if (url == null) {
            throw new SQLException("URL is required");
        }

        if( !acceptsURL(url) ) {
            return null;
        }

        SshConfiguration config = configure(url, info);

        tunnel = new SshTunnel(config);
        tunnel.start();

        // TODO: check if this is enough for most common drivers
        String realUrl = extractUrl(url).replaceFirst(":\\d+", ":" + tunnel.getLocalPort().toString());
        realUrl = realUrl.replaceFirst("://(\\d+\\.\\d+\\.\\d+\\.\\d+|[a-zA-Z0-9_\\-\\.]*)", "://localhost");
        Driver driver = findDriver(realUrl);

        return driver.connect(realUrl, info);
    }

    private SshConfiguration configure(String url, Properties info) throws SQLException {
        SshConfiguration config;

        try {
            URL u = toURL(url);

            Properties properties = new Properties();

            if(info!=null && !info.isEmpty()) {
                properties.putAll(info);
            }

            if(u.getQuery()!=null) {
                String[] parts = u.getQuery().split("&");

                for(String part : parts) {
                    String[] pair = part.split("=");
                    if(pair!=null && pair.length==2) {
                        properties.setProperty(pair[0], pair[1]);
                    }
                }
            }

            properties.setProperty(CONFIG_HOST_REMOTE, u.getHost());
            properties.setProperty(CONFIG_PORT_REMOTE, u.getPort()+"");

            config = new SshConfiguration(properties);
        } catch (Exception e) {
            throw new SQLException(e);
        }

        return config;
    }

    private URL toURL(String url) throws MalformedURLException {
        // NOTE: trick to parse multipart scheme of most common JDBC URLs
        String sanitizedString = null;
        int schemeEndOffset = url.indexOf("://");
        if (-1 == schemeEndOffset) {
            // couldn't find one? try our best here.
            sanitizedString = "http://" + url;
        } else {
            sanitizedString = "http" + url.substring(schemeEndOffset);
        }

        return new URL(sanitizedString);
    }

    private Driver findDriver(String url) throws SQLException {
        Driver realDriver = null;

        for(Enumeration drivers = DriverManager.getDrivers(); drivers.hasMoreElements();) {
            try {
                Driver driver = drivers.nextElement();

                if (driver.acceptsURL(url)) {
                    realDriver = driver;
                    break;
                }
            } catch (SQLException e) {
            }
        }

        if( realDriver == null ) {
            throw new SQLException("Unable to find a driver that accepts " + url);
        }

        return realDriver;
    }

    @Override
    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
        return findDriver(url).getPropertyInfo(url, info);
    }

    @Override
    public int getMajorVersion() {
        return VERSION_MAJOR;
    }

    @Override
    public int getMinorVersion() {
        return VERSION_MINOR;
    }

    @Override
    public boolean jdbcCompliant() {
        return true;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        throw new SQLFeatureNotSupportedException("Feature not supported");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy