class JDBCCore {

    public void executeQuery(ExtensionServiceMessage message) {
        Map<String, ?> request = (Map<String, ?>) message.getObject();
        String replyAddress = ExtensionServiceMessage.extractReplyAddress(message);

        // Getting local copy of JDBC class
        JDBC localJDBC = null;
        synchronized (SYNCH_LOCK) {
            localJDBC = jdbc;
        }
        if (localJDBC == null) {
            if (client != null) {
                client.sendQueryError(replyAddress, this.getClass().getName() + ".closed",
                        "JDBC connection closed before operation could complete.", null);
            }
        }

        // Gather query results and send the appropriate response, or send a query error if an exception is caught
        try {
            if (request.get("query") instanceof String) {
                String queryString = (String) request.get("query");
                // Check if SQL Query is an update statement, or query statement
                if (queryString.trim().toLowerCase().startsWith(SELECT_STATEMENT_IDENTIFIER)) {
                    HashMap[] queryArray = localJDBC.processQuery(queryString);
                    sendDataFromQuery(queryArray, message);
                } else {
                    int data = localJDBC.processPublish(queryString);
                    log.trace("The returned integer value from Publish Query is the following: ", data);

                    // Send empty response back
                    client.sendQueryResponse(204, replyAddress, new LinkedHashMap<>());
                }
            } else if (request.get("query") instanceof List) {
                List queryArray = (List) request.get("query");
                // Check that each batch element is a SQL Update Statement
                for (int i = 0; i < queryArray.size(); i++) {
                    if (queryArray.get(i).toString().trim().toLowerCase().startsWith(SELECT_STATEMENT_IDENTIFIER)) {
                        client.sendQueryError(replyAddress, this.getClass().getName() + ".invalidBatchElement",
                                "The Query Request could not be executed because at least one batch element "
                                + "was not a string representation of a SQL Update Statement.", null);
                        return;
                    }
                }
                int[] data = localJDBC.processBatchPublish(queryArray);
                log.trace("The returned integer array from Publish Query is the following: ", data);

                // Send empty response back
                client.sendQueryResponse(204, replyAddress, new LinkedHashMap<>());
            } else {
                log.error("Query could not be executed because query was not a String.");
                client.sendQueryError(replyAddress, this.getClass().getName() + ".queryNotString", 
                        "The Query Request could not be executed because the query property is "
                        + "not a string.", null);
            }
        } catch (VantiqSQLException e) {
            log.error("Could not execute requested query.", e);
            log.error("Request was: {}", request);
            client.sendQueryError(replyAddress, VantiqSQLException.class.getCanonicalName(), 
                    "Failed to execute query for reason: " + e.getMessage() + 
                    ". Exception was: " + e.getClass().getName() + ". Request was: " + request.get("query"), null);
        } catch (Exception e) {
            log.error("An unexpected error occurred when executing the requested query.", e);
            log.error("Request was: {}", request);
            client.sendQueryError(replyAddress, Exception.class.getCanonicalName(), 
                    "Failed to execute query for reason: " + e.getMessage() + 
                    ". Exception was: " + e.getClass().getName() + ". Request was: " + request.get("query"), null);
        }
    }

    public  JDBCCore(String sourceName, String authToken, String targetVantiqServer);

}