net.collegeman.grails.e3db.Template.java Source code

Java tutorial

Introduction

Here is the source code for net.collegeman.grails.e3db.Template.java

Source

/**
 * e3db Fast database library for Grails
 * Copyright (C) 2009-2010 Collegeman.net, LLC
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package net.collegeman.grails.e3db;

import java.util.*;
import java.sql.*;
import javax.sql.*;
import groovy.lang.*;
import java.util.regex.*;
import org.apache.log4j.*;
import org.springframework.context.ApplicationContext;
import org.springframework.util.StringUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.jdbc.core.simple.*;
import org.springframework.jdbc.datasource.*;
import org.springframework.transaction.*;
import org.springframework.transaction.support.*;

public class Template extends SqlBuffer {

    protected static final Logger log = Logger.getLogger("net.collegeman.grails.e3db");

    private static final Pattern multiLineWhitespace = Pattern.compile("[\\n\\r\\t]");
    private static final Pattern extraSpaces = Pattern.compile(" +");

    private static final String removeWhitespace(String string) {
        string = multiLineWhitespace.matcher(string).replaceAll(" ");
        return extraSpaces.matcher(string).replaceAll(" ");
    }

    protected static final String METHOD_ROW_SET = "rowSet";
    protected static final String METHOD_LIST = "list";
    protected static final String METHOD_OBJECT = "object";

    protected DataSource dataSource;
    protected SimpleJdbcTemplate simpleJdbcTemplate;
    protected TransactionTemplate transactionTemplate;

    // an instance of Query is defined in plugin hook doWithSpring to grab app context and default data source

    protected static ApplicationContext ctx;
    protected static DataSource defaultDataSource;
    protected static SimpleJdbcTemplate defaultSimpleJdbcTemplate;
    protected static TransactionTemplate defaultTransactionTemplate;

    protected static final void setApplicationContext(ApplicationContext applicationContext) {
        ctx = applicationContext;

        // first, go for grails default "dataSource"
        try {
            defaultDataSource = (DataSource) ctx.getBean("dataSource");
            defaultSimpleJdbcTemplate = new SimpleJdbcTemplate(defaultDataSource);
        } catch (NoSuchBeanDefinitionException e) {
            log.warn(
                    "No default DataSource bean named [dataSource] found in application context - a DataSource will need to be created manually for E3DB.");
        }

        // then, try to setup the transaction template
        if (defaultDataSource != null) {
            try {
                defaultTransactionTemplate = new TransactionTemplate(
                        (PlatformTransactionManager) ctx.getBean("transactionManager"));
            } catch (NoSuchBeanDefinitionException e) {
                defaultTransactionTemplate = new TransactionTemplate(
                        new DataSourceTransactionManager(defaultDataSource));
                log.info("DataSourceTranactionManager created by and for E3DB.");
            }
        }
    }

    public static void setDefaultDataSource(DataSource dataSource) {
        defaultDataSource = dataSource;
        defaultSimpleJdbcTemplate = new SimpleJdbcTemplate(defaultDataSource);
        defaultTransactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(defaultDataSource));
    }

    public final TransactionTemplate getTransactionTemplate() {
        if (transactionTemplate != null)
            return transactionTemplate;
        else if (defaultTransactionTemplate != null)
            return defaultTransactionTemplate;
        else {
            log.warn("No Transaction Management available to E3DB.");
            return null;
        }
    }

    protected SimpleJdbcTemplate getSJT() {
        if (simpleJdbcTemplate != null)
            return simpleJdbcTemplate;
        else if (defaultSimpleJdbcTemplate != null)
            return defaultSimpleJdbcTemplate;
        else
            throw new IllegalStateException("DataSource for E3DB Template has not be initialized.");
    }

    protected final static <T> T query(String method, Closure closure, Class<T> requiredType) {
        Template t = new Template();
        closure.setDelegate(t);
        closure.setResolveStrategy(Closure.DELEGATE_FIRST);

        Object sql = closure.call();
        if (hasLength(sql))
            t.sql(String.valueOf(sql));

        return (T) query(method, t.getSql(), requiredType, t.getQueryParams());
    }

    protected final static <T> T query(String method, String sql, Class<T> requiredType, Object... args) {
        if (shouldLogSql())
            logSql(sql, args);

        if (args != null && args.length > 0) {
            if (args[0] instanceof Map) {
                Map map = (Map) args[0];

                if (METHOD_LIST.equals(method)) {
                    return (T) new Template().getSJT().queryForList(sql, map);
                } else if (METHOD_OBJECT.equals(method)) {
                    return (T) new Template().getSJT().queryForObject(sql, requiredType, map);
                } else if (METHOD_ROW_SET.equals(method)) {
                    throw new IllegalStateException(
                            "rows() does not support named parameters. You must use listed parameters instead, e.g., rows('SELECT * FROM ...', param1, param2, ...) or rows { sql('SELECT * FROM ...', param1, param2, ...) }.");
                } else {
                    throw new IllegalStateException("Unrecognized query method: " + method);
                }
            } else {
                if (args[0] instanceof List) {
                    args = ((List) args[0]).toArray();
                }

                if (METHOD_LIST.equals(method)) {
                    return (T) new Template().getSJT().queryForList(sql, args);
                } else if (METHOD_OBJECT.equals(method)) {
                    return (T) new Template().getSJT().queryForObject(sql, requiredType, args);
                } else if (METHOD_ROW_SET.equals(method)) {
                    return (T) new Template().getSJT().getJdbcOperations().queryForRowSet(sql, args);
                } else {
                    throw new IllegalStateException("Unrecognized query method: " + method);
                }
            }
        } else {
            if (METHOD_LIST.equals(method)) {
                return (T) new Template().getSJT().queryForList(sql);
            } else if (METHOD_OBJECT.equals(method)) {
                return (T) new Template().getSJT().queryForObject(sql, requiredType);
            } else if (METHOD_ROW_SET.equals(method)) {
                return (T) new Template().getSJT().getJdbcOperations().queryForRowSet(sql);
            } else {
                throw new IllegalStateException("Unrecognized query method: " + method);
            }
        }
    }

    public final static int exec(Closure closure) {
        Template t = new Template();
        closure.setDelegate(t);
        closure.setResolveStrategy(Closure.DELEGATE_FIRST);

        Object sql = closure.call();
        if (hasLength(sql))
            t.sql(String.valueOf(sql));

        return exec(t.getSql(), t.getQueryParams());
    }

    public final static int exec(String sql, Object... args) {
        if (shouldLogSql())
            logSql(sql, args);
        return new Template().getSJT().update(sql, args);
    }

    public final static void logSql(String sql, Object args) {
        String clearSql = removeWhitespace(sql);

        Object printableArgs;

        if (args != null && args.getClass().isArray())
            printableArgs = Arrays.asList((Object[]) args);
        else
            printableArgs = args;

        if (log.isDebugEnabled())
            log.debug(clearSql + ": " + printableArgs);

        if (System.getProperty("net.collegeman.grails.e3db.printSql") == "true")
            System.out.println("e3db.Template: " + clearSql + ": " + printableArgs);
    }

    public final static boolean shouldLogSql() {
        return (log.isDebugEnabled() || System.getProperty("net.collegeman.grails.e3db.printSql") == "true");
    }

    /**
     * @param name The name of a dataSource bean in Application context.
     */
    public final void dataSource(String name) {
        if (ctx == null)
            throw new IllegalStateException("ApplicationContext not initialized.");
        dataSource((DataSource) ctx.getBean(name));
    }

    public final void dataSource(Map<String, Object> config) {
        Driver driverInstance = null;
        Object driver = config.get("driver");

        try {
            if (driver == null)
                throw new IllegalArgumentException("driver configuration parameter cannot be null.");

            if (driver instanceof Class) {
                driverInstance = (Driver) ((Class) driver).newInstance();
            } else if (driver instanceof String) {
                driverInstance = (Driver) Class.forName((String) driver).newInstance();
            } else if (driver instanceof Driver) {
                driverInstance = (Driver) driver;
            } else {
                throw new IllegalArgumentException("driver is unrecognized type: " + driver.getClass());
            }
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }

        dataSource(new SimpleDriverDataSource(driverInstance, String.valueOf(config.get("url")),
                String.valueOf(config.get("username")), String.valueOf(config.get("password"))));
    }

    /**
     * @param dataSource A JDBC DataSource implementation
     */
    public final void dataSource(DataSource dataSource) {
        if (dataSource == null)
            throw new IllegalArgumentException("dataSource cannot be null.");
        this.dataSource = dataSource;
        simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
        transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource));
    }

    public static final SqlBuffer buffer(Closure closure) {
        SqlBuffer buf = new SqlBuffer();
        closure.setDelegate(buf);
        closure.setResolveStrategy(Closure.DELEGATE_FIRST);
        closure.call();
        return buf;
    }

}