/* * Copyright 2013-2014 the original author or authors. * * 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 hr.helix.sqlstream; import groovy.lang.GString; import groovy.sql.Sql; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.*; import java.util.List; import java.util.logging.Logger; /** * Allows access to {@code groovy.sql.Sql}'s protected/private members. * This is necessary because {@link SqlStreamExtension} could not otherwise * properly extend {@code Sql} class. * * @author Dinko Srkoč * @since 2013-10-30 */ public class SqlWrapper { public static final Logger LOG = Logger.getLogger(Sql.class.getName()); private static Method createConnection; private static Method getStatement; private static Method getPreparedStatement; private static Method closeResources; private static Method getParameters; private static Method asSql; private static NoSuchMethodException initializationException = null; private Sql sql; static { try { createConnection = Sql.class.getDeclaredMethod("createConnection"); getStatement = Sql.class.getDeclaredMethod("getStatement", Connection.class, String.class); getPreparedStatement = Sql.class.getDeclaredMethod("getPreparedStatement", Connection.class, String.class, List.class); closeResources = Sql.class.getDeclaredMethod("closeResources", Connection.class, Statement.class, ResultSet.class); getParameters = Sql.class.getDeclaredMethod("getParameters", GString.class); asSql = Sql.class.getDeclaredMethod("asSql", GString.class, List.class); createConnection.setAccessible(true); getStatement.setAccessible(true); getPreparedStatement.setAccessible(true); closeResources.setAccessible(true); getParameters.setAccessible(true); asSql.setAccessible(true); } catch (NoSuchMethodException e) { initializationException = e; // if any problem arises, store it until SqlWrapper is used } } private SqlWrapper(Sql sql) { this.sql = sql; } public static SqlWrapper wrap(Sql sql) throws NoSuchMethodException { if (initializationException != null) throw initializationException; return new SqlWrapper(sql); } public Connection createConnection() throws SQLException { return (Connection) invokeEx(createConnection); } public Statement getStatement(Connection connection, String query) throws SQLException { return (Statement) invokeEx(getStatement, connection, query); } public void closeResources(Connection connection, Statement statement, ResultSet results) { invoke(closeResources, connection, statement, results); } public List<?> getParameters(GString gstring) { return (List) invoke(getParameters, gstring); } public String asSql(GString gString, List<?> values) { return (String) invoke(asSql, gString, values); } public PreparedStatement getPreparedStatement(Connection connection, String query, List<?> params) throws SQLException { return (PreparedStatement) invokeEx(getPreparedStatement, connection, query, params); } private Object invoke(Method method, Object... params) { try { return method.invoke(sql, params); } catch (IllegalAccessException e) { throw new RuntimeException(e); // not expected to happen } catch (InvocationTargetException e) { throw new RuntimeException(e); // not expected to happen } } private Object invokeEx(Method method, Object... params) throws SQLException { try { return method.invoke(sql, params); } catch (IllegalAccessException e) { throw new RuntimeException(e); // not expected to happen } catch (InvocationTargetException e) { throw (SQLException) e.getCause(); // Sql#`method`() probably throws only SQLException } } }