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}