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         * Class[] for CallableStatement interface.
041         */
042        private static final Class[] callableStatementClass =
043            new Class[] { CallableStatement.class };
044    
045        /**
046         * Class[] for Connection interface.
047         */
048        private static final Class[] connectionClass =
049            new Class[] { Connection.class };
050    
051        /**
052         * Class[] for Driver interface.
053         */
054        private static final Class[] driverClass = new Class[] { Driver.class };
055    
056        /**
057         * The Singleton instance of this class.
058         */
059        private static final ProxyFactory instance = new ProxyFactory();
060    
061        /**
062         * Class[] for ResultSetMetaData interface.
063         */
064        private static final Class[] metaClass =
065            new Class[] { ResultSetMetaData.class };
066    
067        /**
068         * Class[] for PreparedStatement interface.
069         */
070        private static final Class[] preparedStatementClass =
071            new Class[] { PreparedStatement.class };
072    
073        /**
074         * Class[] for ResultSet interface.
075         */
076        private static final Class[] resultSetClass =
077            new Class[] { ResultSet.class };
078    
079        /**
080         * Class[] for Statement interface.
081         */
082        private static final Class[] statementClass =
083            new Class[] { Statement.class };
084    
085        /**
086         * Returns the Singleton instance of this class.
087         *
088         * @return singleton instance
089         */
090        public static ProxyFactory instance() {
091            return instance;
092        }
093    
094        /**
095         * Protected constructor for ProxyFactory subclasses to use.
096         */
097        protected ProxyFactory() {
098            super();
099        }
100    
101        /**
102         * Creates a new proxy <code>CallableStatement</code> object.
103         * @param handler The handler that intercepts/overrides method calls.
104         * @return proxied CallableStatement
105         */
106        public CallableStatement createCallableStatement(InvocationHandler handler) {
107            return (CallableStatement) Proxy.newProxyInstance(
108                handler.getClass().getClassLoader(),
109                callableStatementClass,
110                handler);
111        }
112    
113        /**
114         * Creates a new proxy <code>Connection</code> object.
115         * @param handler The handler that intercepts/overrides method calls.
116         * @return proxied Connection
117         */
118        public Connection createConnection(InvocationHandler handler) {
119            return (Connection) Proxy.newProxyInstance(
120                handler.getClass().getClassLoader(),
121                connectionClass,
122                handler);
123        }
124    
125        /**
126         * Creates a new proxy <code>Driver</code> object.
127         * @param handler The handler that intercepts/overrides method calls.
128         * @return proxied Driver
129         */
130        public Driver createDriver(InvocationHandler handler) {
131            return (Driver) Proxy.newProxyInstance(
132                handler.getClass().getClassLoader(),
133                driverClass,
134                handler);
135        }
136    
137        /**
138         * Creates a new proxy <code>PreparedStatement</code> object.
139         * @param handler The handler that intercepts/overrides method calls.
140         * @return proxied PreparedStatement
141         */
142        public PreparedStatement createPreparedStatement(InvocationHandler handler) {
143            return (PreparedStatement) Proxy.newProxyInstance(
144                handler.getClass().getClassLoader(),
145                preparedStatementClass,
146                handler);
147        }
148    
149        /**
150         * Creates a new proxy <code>ResultSet</code> object.
151         * @param handler The handler that intercepts/overrides method calls.
152         * @return proxied ResultSet
153         */
154        public ResultSet createResultSet(InvocationHandler handler) {
155            return (ResultSet) Proxy.newProxyInstance(
156                handler.getClass().getClassLoader(),
157                resultSetClass,
158                handler);
159        }
160    
161        /**
162         * Creates a new proxy <code>ResultSetMetaData</code> object.
163         * @param handler The handler that intercepts/overrides method calls.
164         * @return proxied ResultSetMetaData
165         */
166        public ResultSetMetaData createResultSetMetaData(InvocationHandler handler) {
167            return (ResultSetMetaData) Proxy.newProxyInstance(
168                handler.getClass().getClassLoader(),
169                metaClass,
170                handler);
171        }
172    
173        /**
174         * Creates a new proxy <code>Statement</code> object.
175         * @param handler The handler that intercepts/overrides method calls.
176         * @return proxied Statement
177         */
178        public Statement createStatement(InvocationHandler handler) {
179            return (Statement) Proxy.newProxyInstance(
180                handler.getClass().getClassLoader(),
181                statementClass,
182                handler);
183        }
184    
185    }