    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.dbutils;
    018
    019import java.lang.reflect.InvocationHandler;
    020import java.lang.reflect.Proxy;
    021import java.sql.CallableStatement;
    022import java.sql.Connection;
    023import java.sql.Driver;
    024import java.sql.PreparedStatement;
    025import java.sql.ResultSet;
    026import java.sql.ResultSetMetaData;
    027import java.sql.Statement;
    028
    029/**
    030 * Creates proxy implementations of JDBC interfaces.  This avoids
    031 * incompatibilities between the JDBC 2 and JDBC 3 interfaces.  This class is
    032 * thread safe.
    033 *
    034 * @see java.lang.reflect.Proxy
    035 * @see java.lang.reflect.InvocationHandler
    036 */
    037public class ProxyFactory {
    038
    039    /**
    040     * The Singleton instance of this class.
    041     */
    042    private static final ProxyFactory instance = new ProxyFactory();
    043
    044    /**
    045     * Returns the Singleton instance of this class.
    046     *
    047     * @return singleton instance
    048     */
    049    public static ProxyFactory instance() {
    050        return instance;
    051    }
    052
    053    /**
    054     * Protected constructor for ProxyFactory subclasses to use.
    055     */
    056    protected ProxyFactory() {
    057    }
    058
    059    /**
    060     * Creates a new proxy {@code CallableStatement} object.
    061     * @param handler The handler that intercepts/overrides method calls.
    062     * @return proxied CallableStatement
    063     */
    064    public CallableStatement createCallableStatement(final InvocationHandler handler) {
    065        return newProxyInstance(CallableStatement.class, handler);
    066    }
    067
    068    /**
    069     * Creates a new proxy {@code Connection} object.
    070     * @param handler The handler that intercepts/overrides method calls.
    071     * @return proxied Connection
    072     */
    073    public Connection createConnection(final InvocationHandler handler) {
    074        return newProxyInstance(Connection.class, handler);
    075    }
    076
    077    /**
    078     * Creates a new proxy {@code Driver} object.
    079     * @param handler The handler that intercepts/overrides method calls.
    080     * @return proxied Driver
    081     */
    082    public Driver createDriver(final InvocationHandler handler) {
    083        return newProxyInstance(Driver.class, handler);
    084    }
    085
    086    /**
    087     * Creates a new proxy {@code PreparedStatement} object.
    088     * @param handler The handler that intercepts/overrides method calls.
    089     * @return proxied PreparedStatement
    090     */
    091    public PreparedStatement createPreparedStatement(final InvocationHandler handler) {
    092        return newProxyInstance(PreparedStatement.class, handler);
    093    }
    094
    095    /**
    096     * Creates a new proxy {@code ResultSet} object.
    097     * @param handler The handler that intercepts/overrides method calls.
    098     * @return proxied ResultSet
    099     */
    100    public ResultSet createResultSet(final InvocationHandler handler) {
    101        return newProxyInstance(ResultSet.class, handler);
    102    }
    103
    104    /**
    105     * Creates a new proxy {@code ResultSetMetaData} object.
    106     * @param handler The handler that intercepts/overrides method calls.
    107     * @return proxied ResultSetMetaData
    108     */
    109    public ResultSetMetaData createResultSetMetaData(final InvocationHandler handler) {
    110        return newProxyInstance(ResultSetMetaData.class, handler);
    111    }
    112
    113    /**
    114     * Creates a new proxy {@code Statement} object.
    115     * @param handler The handler that intercepts/overrides method calls.
    116     * @return proxied Statement
    117     */
    118    public Statement createStatement(final InvocationHandler handler) {
    119        return newProxyInstance(Statement.class, handler);
    120    }
    121
    122    /**
    123     * Convenience method to generate a single-interface proxy using the handler's classloader
    124     *
    125     * @param <T> The type of object to proxy
    126     * @param type The type of object to proxy
    127     * @param handler The handler that intercepts/overrides method calls.
    128     * @return proxied object
    129     */
    130    public <T> T newProxyInstance(final Class<T> type, final InvocationHandler handler) {
    131        return type.cast(Proxy.newProxyInstance(handler.getClass().getClassLoader(), new Class<?>[] {type}, handler));
    132    }
    133
    134}