/* Copyright 2013 The jeo project. All rights reserved. * * 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 io.jeo.sql; import io.jeo.util.Disposer; import javax.sql.DataSource; import java.io.IOException; import java.sql.Connection; import java.sql.SQLException; /** * A database operation. * <p> * Subclasses must implement the {@link #doRun(Connection)} method. Subclasses are encouraged to * use the {@link #open(Object)} when obtaining resources such as statements and result sets. Upon * completion all resources passed to open will be closed in reverse order. * </p> * <p> * Example usage: * <code><pre> * DbOp<Long> count = new DbOp<Long>() { * protected Long doRun(Connection cx) { * ResultSet rs = open(open(cx.createStatement()).executeQuery("SELECT count(*) FROM foo")); * rs.next(); * return rs.getLong(1); * } * }; * </code></pre> * </p> * * @author Justin Deoliveira, OpenGeo * * @param <T> The type of object returned by the operation. */ public abstract class DbOP<T> { /** * resources to close */ Disposer disposer = new Disposer(); /** * Runs the db operation obtaining a new connection from the specified data source. * <p> * The obtained connection will be closed upon completion. * </p> * @param db The data source to obtain a new connection from. * * @return The result of the operation. * * @throws IOException Any errors, including SQLExceptions, that occur. */ public final T run(DataSource db) throws IOException { try { return run(open(db.getConnection())); } catch (SQLException e) { throw propogate(e); } } /** * Runs the db operation with the specified connection. * <p> * It is the responsibility of the caller to close the specified connection. * </p> * * @param cx The db connection. * * @return The result of the operation. * * @throws IOException Any errors, including SQLExceptions, that occur. */ public final T run(Connection cx) throws IOException { try { return doRun(cx); } catch(Exception e) { throw propogate(e); } finally { disposer.close(); } } IOException propogate(Exception err) throws IOException { return err instanceof IOException ? (IOException) err : new IOException(err); } /** * Performs the operation. * * @param cx The database connection. * * @return The result of the operation. * */ protected abstract T doRun(Connection cx) throws Exception; /** * Specifies a resource to close upon completion of the operation. * * @param obj The object to close. * * @return The original object, <tt>obj</tt> */ protected <T> T open(T obj) { return disposer.open(obj); } }