DbUtils.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.dbutils;

  18. import static java.sql.DriverManager.registerDriver;

  19. import java.io.PrintWriter;
  20. import java.lang.reflect.Constructor;
  21. import java.sql.Connection;
  22. import java.sql.Driver;
  23. import java.sql.DriverPropertyInfo;
  24. import java.sql.ResultSet;
  25. import java.sql.SQLException;
  26. import java.sql.SQLFeatureNotSupportedException;
  27. import java.sql.Statement;
  28. import java.util.Properties;
  29. import java.util.logging.Logger;

  30. /**
  31.  * A collection of JDBC helper methods.  This class is thread safe.
  32.  */
  33. public final class DbUtils {

  34.     /**
  35.      * Simple {@link Driver} proxy class that proxies a JDBC Driver loaded dynamically.
  36.      *
  37.      * @since 1.6
  38.      */
  39.     static final class DriverProxy implements Driver {

  40.         /**
  41.          * The adapted JDBC Driver loaded dynamically.
  42.          */
  43.         private final Driver adapted;

  44.         /**
  45.          * Creates a new JDBC Driver that adapts a JDBC Driver loaded dynamically.
  46.          *
  47.          * @param adapted the adapted JDBC Driver loaded dynamically.
  48.          */
  49.         public DriverProxy(final Driver adapted) {
  50.             this.adapted = adapted;
  51.         }

  52.         /**
  53.          * {@inheritDoc}
  54.          */
  55.         @Override
  56.         public boolean acceptsURL(final String url) throws SQLException {
  57.             return adapted.acceptsURL(url);
  58.         }

  59.         /**
  60.          * {@inheritDoc}
  61.          */
  62.         @Override
  63.         public Connection connect(final String url, final Properties info) throws SQLException {
  64.             return adapted.connect(url, info);
  65.         }

  66.         /**
  67.          * {@inheritDoc}
  68.          */
  69.         @Override
  70.         public int getMajorVersion() {
  71.             return adapted.getMajorVersion();
  72.         }

  73.         /**
  74.          * {@inheritDoc}
  75.          */
  76.         @Override
  77.         public int getMinorVersion() {
  78.             return adapted.getMinorVersion();
  79.         }

  80.         /**
  81.          * Java 1.7 method.
  82.          */
  83.         @Override
  84.         public Logger getParentLogger() throws SQLFeatureNotSupportedException {
  85.             return adapted.getParentLogger();
  86.         }

  87.         /**
  88.          * {@inheritDoc}
  89.          */
  90.         @Override
  91.         public DriverPropertyInfo[] getPropertyInfo(final String url, final Properties info) throws SQLException {
  92.             return adapted.getPropertyInfo(url, info);
  93.         }

  94.         /**
  95.          * {@inheritDoc}
  96.          */
  97.         @Override
  98.         public boolean jdbcCompliant() {
  99.             return adapted.jdbcCompliant();
  100.         }

  101.     }

  102.     /**
  103.      * Close a {@code Connection}, avoid closing if null.
  104.      *
  105.      * @param conn Connection to close.
  106.      * @throws SQLException if a database access error occurs
  107.      */
  108.     public static void close(final Connection conn) throws SQLException {
  109.         if (conn != null) {
  110.             conn.close();
  111.         }
  112.     }

  113.     /**
  114.      * Close a {@code ResultSet}, avoid closing if null.
  115.      *
  116.      * @param resultSet ResultSet to close.
  117.      * @throws SQLException if a database access error occurs
  118.      */
  119.     public static void close(final ResultSet resultSet) throws SQLException {
  120.         if (resultSet != null) {
  121.             resultSet.close();
  122.         }
  123.     }

  124.     /**
  125.      * Close a {@code Statement}, avoid closing if null.
  126.      *
  127.      * @param stmt Statement to close.
  128.      * @throws SQLException if a database access error occurs
  129.      */
  130.     public static void close(final Statement stmt) throws SQLException {
  131.         if (stmt != null) {
  132.             stmt.close();
  133.         }
  134.     }

  135.     /**
  136.      * Close a {@code Connection}, avoid closing if null and hide
  137.      * any SQLExceptions that occur.
  138.      *
  139.      * @param conn Connection to close.
  140.      */
  141.     public static void closeQuietly(final Connection conn) {
  142.         try {
  143.             close(conn);
  144.         } catch (final SQLException e) { // NOPMD
  145.             // quiet
  146.         }
  147.     }

  148.     /**
  149.      * Close a {@code Connection}, {@code Statement} and
  150.      * {@code ResultSet}.  Avoid closing if null and hide any
  151.      * SQLExceptions that occur.
  152.      *
  153.      * @param conn Connection to close.
  154.      * @param stmt Statement to close.
  155.      * @param rs ResultSet to close.
  156.      */
  157.     public static void closeQuietly(final Connection conn, final Statement stmt,
  158.             final ResultSet rs) {

  159.         try {
  160.             closeQuietly(rs);
  161.         } finally {
  162.             try {
  163.                 closeQuietly(stmt);
  164.             } finally {
  165.                 closeQuietly(conn);
  166.             }
  167.         }

  168.     }

  169.     /**
  170.      * Close a {@code ResultSet}, avoid closing if null and hide any
  171.      * SQLExceptions that occur.
  172.      *
  173.      * @param resultSet ResultSet to close.
  174.      */
  175.     public static void closeQuietly(final ResultSet resultSet) {
  176.         try {
  177.             close(resultSet);
  178.         } catch (final SQLException e) { // NOPMD
  179.             // quiet
  180.         }
  181.     }

  182.     /**
  183.      * Close a {@code Statement}, avoid closing if null and hide
  184.      * any SQLExceptions that occur.
  185.      *
  186.      * @param stmt Statement to close.
  187.      */
  188.     public static void closeQuietly(final Statement stmt) {
  189.         try {
  190.             close(stmt);
  191.         } catch (final SQLException e) { // NOPMD
  192.             // quiet
  193.         }
  194.     }

  195.     /**
  196.      * Commits a {@code Connection} then closes it, avoid closing if null.
  197.      *
  198.      * @param conn Connection to close.
  199.      * @throws SQLException if a database access error occurs
  200.      */
  201.     public static void commitAndClose(final Connection conn) throws SQLException {
  202.         if (conn != null) {
  203.             try {
  204.                 conn.commit();
  205.             } finally {
  206.                 conn.close();
  207.             }
  208.         }
  209.     }

  210.     /**
  211.      * Commits a {@code Connection} then closes it, avoid closing if null
  212.      * and hide any SQLExceptions that occur.
  213.      *
  214.      * @param conn Connection to close.
  215.      */
  216.     public static void commitAndCloseQuietly(final Connection conn) {
  217.         try {
  218.             commitAndClose(conn);
  219.         } catch (final SQLException e) { // NOPMD
  220.             // quiet
  221.         }
  222.     }

  223.     /**
  224.      * Loads and registers a database driver class.
  225.      * If this succeeds, it returns true, else it returns false.
  226.      *
  227.      * @param classLoader the class loader used to load the driver class
  228.      * @param driverClassName of driver to load
  229.      * @return boolean {@code true} if the driver was found, otherwise {@code false}
  230.      * @since 1.4
  231.      */
  232.     public static boolean loadDriver(final ClassLoader classLoader, final String driverClassName) {
  233.         try {
  234.             final Class<?> loadedClass = classLoader.loadClass(driverClassName);

  235.             if (!Driver.class.isAssignableFrom(loadedClass)) {
  236.                 return false;
  237.             }

  238.             @SuppressWarnings("unchecked") // guarded by previous check
  239.             final
  240.             Class<Driver> driverClass = (Class<Driver>) loadedClass;
  241.             final Constructor<Driver> driverConstructor = driverClass.getConstructor();

  242.             // make Constructor accessible if it is private
  243.             @SuppressWarnings("deprecation")
  244.             // TODO This is deprecated in Java9 and canAccess() should be used. Adding suppression for building on
  245.             //      later JDKs without a warning.
  246.             final boolean isConstructorAccessible = driverConstructor.isAccessible();
  247.             if (!isConstructorAccessible) {
  248.                 driverConstructor.setAccessible(true);
  249.             }

  250.             try {
  251.                 final Driver driver = driverConstructor.newInstance();
  252.                 registerDriver(new DriverProxy(driver));
  253.             } finally {
  254.                 driverConstructor.setAccessible(isConstructorAccessible);
  255.             }

  256.             return true;
  257.         } catch (final Exception e) {
  258.             return false;
  259.         }
  260.     }

  261.     /**
  262.      * Loads and registers a database driver class.
  263.      * If this succeeds, it returns true, else it returns false.
  264.      *
  265.      * @param driverClassName of driver to load
  266.      * @return boolean {@code true} if the driver was found, otherwise {@code false}
  267.      */
  268.     public static boolean loadDriver(final String driverClassName) {
  269.         return loadDriver(DbUtils.class.getClassLoader(), driverClassName);
  270.     }

  271.     /**
  272.      * Print the stack trace for a SQLException to STDERR.
  273.      *
  274.      * @param e SQLException to print stack trace of
  275.      */
  276.     public static void printStackTrace(final SQLException e) {
  277.         printStackTrace(e, new PrintWriter(System.err));
  278.     }

  279.     /**
  280.      * Print the stack trace for a SQLException to a
  281.      * specified PrintWriter.
  282.      *
  283.      * @param e SQLException to print stack trace of
  284.      * @param pw PrintWriter to print to
  285.      */
  286.     public static void printStackTrace(final SQLException e, final PrintWriter pw) {

  287.         SQLException next = e;
  288.         while (next != null) {
  289.             next.printStackTrace(pw);
  290.             next = next.getNextException();
  291.             if (next != null) {
  292.                 pw.println("Next SQLException:");
  293.             }
  294.         }
  295.     }

  296.     /**
  297.      * Print warnings on a Connection to STDERR.
  298.      *
  299.      * @param conn Connection to print warnings from
  300.      */
  301.     public static void printWarnings(final Connection conn) {
  302.         printWarnings(conn, new PrintWriter(System.err));
  303.     }

  304.     /**
  305.      * Print warnings on a Connection to a specified PrintWriter.
  306.      *
  307.      * @param conn Connection to print warnings from
  308.      * @param pw PrintWriter to print to
  309.      */
  310.     public static void printWarnings(final Connection conn, final PrintWriter pw) {
  311.         if (conn != null) {
  312.             try {
  313.                 printStackTrace(conn.getWarnings(), pw);
  314.             } catch (final SQLException e) {
  315.                 printStackTrace(e, pw);
  316.             }
  317.         }
  318.     }

  319.     /**
  320.      * Rollback any changes made on the given connection.
  321.      * @param conn Connection to rollback.  A null value is legal.
  322.      * @throws SQLException if a database access error occurs
  323.      */
  324.     public static void rollback(final Connection conn) throws SQLException {
  325.         if (conn != null) {
  326.             conn.rollback();
  327.         }
  328.     }


  329.     /**
  330.      * Performs a rollback on the {@code Connection} then closes it,
  331.      * avoid closing if null.
  332.      *
  333.      * @param conn Connection to rollback.  A null value is legal.
  334.      * @throws SQLException if a database access error occurs
  335.      * @since 1.1
  336.      */
  337.     public static void rollbackAndClose(final Connection conn) throws SQLException {
  338.         if (conn != null) {
  339.             try {
  340.                 conn.rollback();
  341.             } finally {
  342.                 conn.close();
  343.             }
  344.         }
  345.     }

  346.     /**
  347.      * Performs a rollback on the {@code Connection} then closes it,
  348.      * avoid closing if null and hide any SQLExceptions that occur.
  349.      *
  350.      * @param conn Connection to rollback.  A null value is legal.
  351.      * @since 1.1
  352.      */
  353.     public static void rollbackAndCloseQuietly(final Connection conn) {
  354.         try {
  355.             rollbackAndClose(conn);
  356.         } catch (final SQLException e) { // NOPMD
  357.             // quiet
  358.         }
  359.     }

  360.     /**
  361.      * Performs a rollback on the <code>Connection</code>, avoid
  362.      * closing if null and hide any SQLExceptions that occur.
  363.      *
  364.      * @param conn Connection to rollback.  A null value is legal.
  365.      * @since DbUtils 2.0
  366.      */
  367.     public static void rollbackQuietly(final Connection conn) {
  368.         try {
  369.             rollback(conn);
  370.         } catch (final SQLException e) { // NOPMD
  371.             // quiet
  372.         }
  373.     }

  374.     /**
  375.      * Default constructor.
  376.      *
  377.      * Utility classes should not have a public or default constructor,
  378.      * but this one preserves retro-compatibility.
  379.      *
  380.      * @since 1.4
  381.      */
  382.     public DbUtils() {
  383.         // do nothing
  384.     }

  385. }