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

flabbergast.JdbcUriHandler Maven / Gradle / Ivy

package flabbergast;

import flabbergast.ReflectedFrame.Transform;
import flabbergast.TaskMaster.LibraryFailure;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class JdbcUriHandler implements UriHandler {

    private static Map> connection_hooks = new HashMap>();
    static {
        connection_hooks.put("database", new Transform() {
            public Object invoke(Connection c) {
                try {
                    return c.getCatalog();
                } catch (SQLException e) {
                    return Unit.NULL;
                }
            }
        });
        connection_hooks.put("product_name", new Transform() {
            public Object invoke(Connection c) {
                try {
                    return c.getMetaData().getDatabaseProductName();
                } catch (SQLException e) {
                    return Unit.NULL;
                }
            }
        });
        connection_hooks.put("product_version", new Transform() {
            public Object invoke(Connection c) {
                try {
                    return c.getMetaData().getDatabaseProductVersion();
                } catch (SQLException e) {
                    return Unit.NULL;
                }
            }
        });
        connection_hooks.put("driver_name", new Transform() {
            public Object invoke(Connection c) {
                try {
                    return c.getMetaData().getDriverName();
                } catch (SQLException e) {
                    return Unit.NULL;
                }
            }
        });
        connection_hooks.put("driver_version", new Transform() {
            public Object invoke(Connection c) {
                try {
                    return c.getMetaData().getDriverVersion();
                } catch (SQLException e) {
                    return Unit.NULL;
                }
            }
        });
        connection_hooks.put("platform", new Transform() {
            public Object invoke(Connection c) {
                return "JDBC";
            }
        });
    }
    public static String parseUri(String uri_fragment, Properties properties,
                                  String user_param, String password_param, String db_param,
                                  Ptr err) {
        int host_start = 0;
        int user_end = 0;
        while (user_end < uri_fragment.length()
                && (Character.isLetterOrDigit(uri_fragment.charAt(user_end)) || uri_fragment
                    .charAt(user_end) == '_')) {
            user_end++;
        }
        if (user_end == uri_fragment.length()) {
            // We know this is malformed.
            err.set("Missing “/” followed by database in SQL URI.");
            return null;
        } else {
            switch (uri_fragment.charAt(user_end)) {
            case '@' :
                // End of user string.
                properties.setProperty(user_param,
                                       uri_fragment.substring(0, user_end));
                host_start = user_end + 1;
                break;
            case ':' :
                // Possible password. Might be port.
                int password_end = user_end + 1;
                while (password_end < uri_fragment.length()
                        && "/@".indexOf(uri_fragment.charAt(password_end)) == -1) {
                    password_end++;
                }
                if (password_end == uri_fragment.length()) {
                    // We know this is malformed.
                    err.set("Missing “/” followed by database in SQL URI.");
                    return null;
                } else if (uri_fragment.charAt(password_end) == '@') {
                    host_start = password_end + 1;
                    properties.setProperty(user_param,
                                           uri_fragment.substring(0, user_end));
                    properties.setProperty(password_param, uri_fragment
                                           .substring(user_end + 1, password_end));
                }
                // Else, this is really the host:port.
                break;
            default :
                // This is really the host.
                break;
            }
        }
        int host_end = host_start;
        while (host_end < uri_fragment.length()
                && "/:".indexOf(uri_fragment.charAt(host_end)) == -1) {
            // IPv6 address?
            if (uri_fragment.charAt(host_end) == '[') {
                while (host_end < uri_fragment.length()
                        && uri_fragment.charAt(host_end) != ']') {
                    host_end++;
                }
            }
            host_end++;
        }
        if (host_end >= uri_fragment.length()) {
            err.set("Missing “/” followed by database in SQL URI.");
            return null;
        }
        if (uri_fragment.charAt(host_end) == ':') {
            host_end++;
            while (host_end < uri_fragment.length()
                    && Character.isDigit(uri_fragment.charAt(host_end))) {
                host_end++;
            }
            if (host_end == uri_fragment.length()) {
                err.set("Missing “/” followed by database in SQL URI.");
                return null;
            }
            if (uri_fragment.charAt(host_end) != '/') {
                err.set("Non-numeric data in port in SQL URI.");
                return null;
            }
        }
        if (uri_fragment.charAt(host_end) != '/') {
            err.set("Junk after host in SQL URI.");
            return null;
        }
        int db_end = host_end + 1;
        while (db_end < uri_fragment.length()
                && uri_fragment.charAt(db_end) != '/') {
            db_end++;
        }
        if (db_end < uri_fragment.length()) {
            err.set("Junk after database in SQL URI.");
            return null;
        }
        if (db_param == null) {
            return uri_fragment.substring(host_start);
        } else {
            properties.setProperty(db_param,
                                   uri_fragment.substring(host_end + 1));
            return uri_fragment.substring(host_start, host_end);
        }
    }
    private ResourcePathFinder finder;

    public JdbcUriHandler() {
    }

    public ResourcePathFinder getFinder() {
        return finder;
    }

    public String getUriName() {
        return "JDBC gateway";
    }
    private Object marshall(String s) {
        if (s == null || s.length() == 0) {
            return Unit.NULL;
        }
        return new SimpleStringish(s);
    }
    public Computation resolveUri(TaskMaster task_master, String uri,
                                  Ptr reason) {
        if (!uri.startsWith("sql:")) {
            reason.set(LibraryFailure.MISSING);
            return null;
        }
        SourceReference src_ref = null;
        try {
            Properties params = new Properties();
            int first_colon = 5;
            while (first_colon < uri.length() && uri.charAt(first_colon) != ':') {
                first_colon++;
            }
            if (first_colon == uri.length()) {
                return new FailureComputation(task_master,
                                              new JavaSourceReference(), "Bad provider in URI “"
                                              + uri + "”.");
            }
            String provider = uri.substring(4, first_colon);
            int question_mark = first_colon;
            while (question_mark < uri.length()
                    && uri.charAt(question_mark) != '?') {
                question_mark++;
            }
            String uri_fragment = uri.substring(first_colon + 1, question_mark);
            if (question_mark < uri.length() - 1) {
                for (String param_str : uri.substring(question_mark + 1).split(
                            "&")) {
                    if (param_str.length() == 0) {
                        continue;
                    }
                    String[] parts = param_str.split("=", 2);
                    if (parts.length != 2) {
                        return new FailureComputation(task_master,
                                                      new JavaSourceReference(), "Bad parameter “"
                                                      + param_str + "”.");
                    }
                    params.setProperty(parts[0], parts[1]);
                }
            }

            Ptr err = new Ptr ("Bad URI.");
            Properties properties = new Properties();
            String jdbc_uri = JdbcParser.parse(provider, uri_fragment, params,
                                               properties, finder, err);
            if (jdbc_uri == null) {
                return new FailureComputation(task_master,
                                              new JavaSourceReference(), err.get());
            }
            Connection connection = DriverManager.getConnection(jdbc_uri,
                                    properties);
            if (connection == null) {
                reason.set(LibraryFailure.CORRUPT);
                return null;
            }
            ReflectedFrame connection_proxy = ReflectedFrame.create(
                                                  task_master, connection, connection_hooks);
            int plus_position = provider.indexOf('+');
            connection_proxy.set("provider", new SimpleStringish(plus_position == -1 ? provider : provider.substring(0, plus_position)));
            return new Precomputation(connection_proxy);
        } catch (SQLException e) {
            if (src_ref == null) {
                src_ref = new JavaSourceReference();
            }
            return new FailureComputation(task_master, src_ref, e.getMessage());
        }
    }
    public void setFinder(ResourcePathFinder finder) {
        this.finder = finder;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy