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     */
017    package org.apache.commons.dbutils;
018    
019    import java.lang.reflect.InvocationHandler;
020    import java.lang.reflect.Proxy;
021    import java.sql.CallableStatement;
022    import java.sql.Connection;
023    import java.sql.Driver;
024    import java.sql.PreparedStatement;
025    import java.sql.ResultSet;
026    import java.sql.ResultSetMetaData;
027    import 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     */
037    public 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            super();
058        }
059    
060        /**
061         * Convenience method to generate a single-interface proxy using the handler's classloader
062         *
063         * @param <T> The type of object to proxy
064         * @param type The type of object to proxy
065         * @param handler The handler that intercepts/overrides method calls.
066         * @return proxied object
067         */
068        public <T> T newProxyInstance(Class<T> type, InvocationHandler handler) {
069            return type.cast(Proxy.newProxyInstance(handler.getClass().getClassLoader(), new Class<?>[] {type}, handler));
070        }
071    
072        /**
073         * Creates a new proxy <code>CallableStatement</code> object.
074         * @param handler The handler that intercepts/overrides method calls.
075         * @return proxied CallableStatement
076         */
077        public CallableStatement createCallableStatement(InvocationHandler handler) {
078            return newProxyInstance(CallableStatement.class, handler);
079        }
080    
081        /**
082         * Creates a new proxy <code>Connection</code> object.
083         * @param handler The handler that intercepts/overrides method calls.
084         * @return proxied Connection
085         */
086        public Connection createConnection(InvocationHandler handler) {
087            return newProxyInstance(Connection.class, handler);
088        }
089    
090        /**
091         * Creates a new proxy <code>Driver</code> object.
092         * @param handler The handler that intercepts/overrides method calls.
093         * @return proxied Driver
094         */
095        public Driver createDriver(InvocationHandler handler) {
096            return newProxyInstance(Driver.class, handler);
097        }
098    
099        /**
100         * Creates a new proxy <code>PreparedStatement</code> object.
101         * @param handler The handler that intercepts/overrides method calls.
102         * @return proxied PreparedStatement
103         */
104        public PreparedStatement createPreparedStatement(InvocationHandler handler) {
105            return newProxyInstance(PreparedStatement.class, handler);
106        }
107    
108        /**
109         * Creates a new proxy <code>ResultSet</code> object.
110         * @param handler The handler that intercepts/overrides method calls.
111         * @return proxied ResultSet
112         */
113        public ResultSet createResultSet(InvocationHandler handler) {
114            return newProxyInstance(ResultSet.class, handler);
115        }
116    
117        /**
118         * Creates a new proxy <code>ResultSetMetaData</code> object.
119         * @param handler The handler that intercepts/overrides method calls.
120         * @return proxied ResultSetMetaData
121         */
122        public ResultSetMetaData createResultSetMetaData(InvocationHandler handler) {
123            return newProxyInstance(ResultSetMetaData.class, handler);
124        }
125    
126        /**
127         * Creates a new proxy <code>Statement</code> object.
128         * @param handler The handler that intercepts/overrides method calls.
129         * @return proxied Statement
130         */
131        public Statement createStatement(InvocationHandler handler) {
132            return newProxyInstance(Statement.class, handler);
133        }
134    
135    }