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