Home » apache-openjpa-1.1.0-source » org.apache.openjpa.lib » jdbc » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements.  See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership.  The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License.  You may obtain a copy of the License at
    9    *
   10    * http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing,
   13    * software distributed under the License is distributed on an
   14    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    * KIND, either express or implied.  See the License for the
   16    * specific language governing permissions and limitations
   17    * under the License.    
   18    */
   19   package org.apache.openjpa.lib.jdbc;
   20   
   21   import java.lang.reflect.Method;
   22   import java.sql.CallableStatement;
   23   import java.sql.Connection;
   24   import java.sql.DatabaseMetaData;
   25   import java.sql.PreparedStatement;
   26   import java.sql.ResultSet;
   27   import java.sql.SQLException;
   28   import java.sql.SQLWarning;
   29   import java.sql.Savepoint;
   30   import java.sql.Statement;
   31   import java.util.HashMap;
   32   import java.util.Map;
   33   
   34   import org.apache.commons.lang.exception.NestableRuntimeException;
   35   import org.apache.openjpa.lib.util.Closeable;
   36   import org.apache.openjpa.lib.util.Localizer;
   37   import serp.util.Numbers;
   38   
   39   /**
   40    * Wrapper around an existing connection. Subclasses can override the
   41    * methods whose behavior they mean to change. The <code>equals</code> and
   42    * <code>hashCode</code> methods pass through to the base underlying data
   43    * store connection.
   44    *
   45    * @author Abe White
   46    */
   47   public class DelegatingConnection implements Connection, Closeable {
   48   
   49       // jdbc 3 method keys
   50       private static final Object SET_HOLDABILITY = new Object();
   51       private static final Object GET_HOLDABILITY = new Object();
   52       private static final Object SET_SAVEPOINT_NONAME = new Object();
   53       private static final Object SET_SAVEPOINT = new Object();
   54       private static final Object ROLLBACK_SAVEPOINT = new Object();
   55       private static final Object RELEASE_SAVEPOINT = new Object();
   56       private static final Object CREATE_STATEMENT = new Object();
   57       private static final Object PREPARE_STATEMENT = new Object();
   58       private static final Object PREPARE_CALL = new Object();
   59       private static final Object PREPARE_WITH_KEYS = new Object();
   60       private static final Object PREPARE_WITH_INDEX = new Object();
   61       private static final Object PREPARE_WITH_NAMES = new Object();
   62   
   63       private static final Localizer _loc = Localizer.forPackage
   64           (DelegatingConnection.class);
   65   
   66       private static final Map _jdbc3;
   67   
   68       static {
   69           boolean jdbc3 = false;
   70           Method m = null;
   71           try {
   72               m = Connection.class.getMethod("setSavepoint",
   73                   new Class[]{ String.class });
   74               jdbc3 = true;
   75           } catch (Throwable t) {
   76           }
   77   
   78           if (jdbc3) {
   79               _jdbc3 = new HashMap();
   80               _jdbc3.put(SET_SAVEPOINT, m);
   81           } else
   82               _jdbc3 = null;
   83       }
   84   
   85       private final Connection _conn;
   86       private final DelegatingConnection _del;
   87   
   88       public DelegatingConnection(Connection conn) {
   89           _conn = conn;
   90           if (conn instanceof DelegatingConnection)
   91               _del = (DelegatingConnection) _conn;
   92           else
   93               _del = null;
   94       }
   95   
   96       /**
   97        * Return the wrapped connection.
   98        */
   99       public Connection getDelegate() {
  100           return _conn;
  101       }
  102   
  103       /**
  104        * Return the base underlying data store connection.
  105        */
  106       public Connection getInnermostDelegate() {
  107           return (_del == null) ? _conn : _del.getInnermostDelegate();
  108       }
  109   
  110       public int hashCode() {
  111           return getInnermostDelegate().hashCode();
  112       }
  113   
  114       public boolean equals(Object other) {
  115           if (other == this)
  116               return true;
  117           if (other instanceof DelegatingConnection)
  118               other = ((DelegatingConnection) other).getInnermostDelegate();
  119           return getInnermostDelegate().equals(other);
  120       }
  121   
  122       public String toString() {
  123           StringBuffer buf = new StringBuffer("conn ").append(hashCode());
  124           appendInfo(buf);
  125           return buf.toString();
  126       }
  127   
  128       protected void appendInfo(StringBuffer buf) {
  129           if (_del != null)
  130               _del.appendInfo(buf);
  131       }
  132   
  133       public Statement createStatement() throws SQLException {
  134           return createStatement(true);
  135       }
  136   
  137       /**
  138        * Create a statement, with the option of not wrapping it in a
  139        * {@link DelegatingStatement}, which is the default.
  140        */
  141       protected Statement createStatement(boolean wrap) throws SQLException {
  142           Statement stmnt;
  143           if (_del != null)
  144               stmnt = _del.createStatement(false);
  145           else
  146               stmnt = _conn.createStatement();
  147           if (wrap)
  148               stmnt = new DelegatingStatement(stmnt, this);
  149           return stmnt;
  150       }
  151   
  152       public PreparedStatement prepareStatement(String str) throws SQLException {
  153           return prepareStatement(str, true);
  154       }
  155   
  156       /**
  157        * Prepare a statement, with the option of not wrapping it in a
  158        * {@link DelegatingPreparedStatement}, which is the default.
  159        */
  160       protected PreparedStatement prepareStatement(String str, boolean wrap)
  161           throws SQLException {
  162           PreparedStatement stmnt;
  163           if (_del != null)
  164               stmnt = _del.prepareStatement(str, false);
  165           else
  166               stmnt = _conn.prepareStatement(str, ResultSet.TYPE_FORWARD_ONLY, 
  167                   ResultSet.CONCUR_READ_ONLY);
  168           if (wrap)
  169               stmnt = new DelegatingPreparedStatement(stmnt, this);
  170           return stmnt;
  171       }
  172   
  173       public CallableStatement prepareCall(String str) throws SQLException {
  174           return prepareCall(str, true);
  175       }
  176   
  177       /**
  178        * Prepare a call, with the option of not wrapping it in a
  179        * {@link DelegatingCallableStatement}, which is the default.
  180        */
  181       protected CallableStatement prepareCall(String str, boolean wrap)
  182           throws SQLException {
  183           CallableStatement stmnt;
  184           if (_del != null)
  185               stmnt = _del.prepareCall(str, false);
  186           else
  187               stmnt = _conn.prepareCall(str);
  188           if (wrap)
  189               stmnt = new DelegatingCallableStatement(stmnt, this);
  190           return stmnt;
  191       }
  192   
  193       public String nativeSQL(String str) throws SQLException {
  194           return _conn.nativeSQL(str);
  195       }
  196   
  197       public void setAutoCommit(boolean bool) throws SQLException {
  198           _conn.setAutoCommit(bool);
  199       }
  200   
  201       public boolean getAutoCommit() throws SQLException {
  202           return _conn.getAutoCommit();
  203       }
  204   
  205       public void commit() throws SQLException {
  206           _conn.commit();
  207       }
  208   
  209       public void rollback() throws SQLException {
  210           _conn.rollback();
  211       }
  212   
  213       public void close() throws SQLException {
  214           _conn.close();
  215       }
  216   
  217       public boolean isClosed() throws SQLException {
  218           return _conn.isClosed();
  219       }
  220   
  221       public DatabaseMetaData getMetaData() throws SQLException {
  222           return getMetaData(true);
  223       }
  224   
  225       /**
  226        * Return the metadata, with the option of not wrapping it in a
  227        * {@link DelegatingDatabaseMetaData}, which is the default.
  228        */
  229       protected DatabaseMetaData getMetaData(boolean wrap) throws SQLException {
  230           DatabaseMetaData meta;
  231           if (_del != null)
  232               meta = _del.getMetaData(false);
  233           else
  234               meta = _conn.getMetaData();
  235           if (wrap)
  236               meta = new DelegatingDatabaseMetaData(meta, this);
  237           return meta;
  238       }
  239   
  240       public void setReadOnly(boolean bool) throws SQLException {
  241           _conn.setReadOnly(bool);
  242       }
  243   
  244       public boolean isReadOnly() throws SQLException {
  245           return _conn.isReadOnly();
  246       }
  247   
  248       public void setCatalog(String str) throws SQLException {
  249           _conn.setCatalog(str);
  250       }
  251   
  252       public String getCatalog() throws SQLException {
  253           return _conn.getCatalog();
  254       }
  255   
  256       public void setTransactionIsolation(int i) throws SQLException {
  257           _conn.setTransactionIsolation(i);
  258       }
  259   
  260       public int getTransactionIsolation() throws SQLException {
  261           return _conn.getTransactionIsolation();
  262       }
  263   
  264       public SQLWarning getWarnings() throws SQLException {
  265           return _conn.getWarnings();
  266       }
  267   
  268       public void clearWarnings() throws SQLException {
  269           _conn.clearWarnings();
  270       }
  271   
  272       public Statement createStatement(int type, int concur) throws SQLException {
  273           return createStatement(type, concur, true);
  274       }
  275   
  276       /**
  277        * Create a statement, with the option of not wrapping it in a
  278        * {@link DelegatingStatement}, which is the default.
  279        */
  280       protected Statement createStatement(int type, int concur, boolean wrap)
  281           throws SQLException {
  282           Statement stmnt;
  283           if (_del != null)
  284               stmnt = _del.createStatement(type, concur, false);
  285           else
  286               stmnt = _conn.createStatement(type, concur);
  287           if (wrap)
  288               stmnt = new DelegatingStatement(stmnt, this);
  289           return stmnt;
  290       }
  291   
  292       public PreparedStatement prepareStatement(String str, int type, int concur)
  293           throws SQLException {
  294           return prepareStatement(str, type, concur, true);
  295       }
  296   
  297       /**
  298        * Prepare a statement, with the option of not wrapping it in a
  299        * {@link DelegatingPreparedStatement}, which is the default.
  300        */
  301       protected PreparedStatement prepareStatement(String str, int type,
  302           int concur, boolean wrap) throws SQLException {
  303           PreparedStatement stmnt;
  304           if (_del != null)
  305               stmnt = _del.prepareStatement(str, type, concur, false);
  306           else
  307               stmnt = _conn.prepareStatement(str, type, concur);
  308           if (wrap)
  309               stmnt = new DelegatingPreparedStatement(stmnt, this);
  310           return stmnt;
  311       }
  312   
  313       public CallableStatement prepareCall(String str, int type, int concur)
  314           throws SQLException {
  315           return prepareCall(str, type, concur, true);
  316       }
  317   
  318       /**
  319        * Prepare a call, with the option of not wrapping it in a
  320        * {@link DelegatingCallableStatement}, which is the default.
  321        */
  322       protected CallableStatement prepareCall(String str, int type, int concur,
  323           boolean wrap) throws SQLException {
  324           CallableStatement stmnt;
  325           if (_del != null)
  326               stmnt = _del.prepareCall(str, type, concur, false);
  327           else
  328               stmnt = _conn.prepareCall(str, type, concur);
  329           if (wrap)
  330               stmnt = new DelegatingCallableStatement(stmnt, this);
  331           return stmnt;
  332       }
  333   
  334       public Map getTypeMap() throws SQLException {
  335           return _conn.getTypeMap();
  336       }
  337   
  338       public void setTypeMap(Map map) throws SQLException {
  339           _conn.setTypeMap(map);
  340       }
  341   
  342       // JDBC 3.0 methods follow; these are required to be able to
  343       // compile against JDK 1.4; these methods will not work on
  344       // previous JVMs
  345   
  346       public void setHoldability(int holdability) throws SQLException {
  347           assertJDBC3();
  348           Method m = (Method) _jdbc3.get(SET_HOLDABILITY);
  349           if (m == null)
  350               m = createJDBC3Method(SET_HOLDABILITY, "setHoldability",
  351                   new Class[]{ int.class });
  352           invokeJDBC3(m, new Object[]{ Numbers.valueOf(holdability) });
  353       }
  354   
  355       public int getHoldability() throws SQLException {
  356           assertJDBC3();
  357           Method m = (Method) _jdbc3.get(GET_HOLDABILITY);
  358           if (m == null)
  359               m = createJDBC3Method(GET_HOLDABILITY, "getHoldability", null);
  360           return ((Number) invokeJDBC3(m, null)).intValue();
  361       }
  362   
  363       public Savepoint setSavepoint() throws SQLException {
  364           assertJDBC3();
  365           Method m = (Method) _jdbc3.get(SET_SAVEPOINT_NONAME);
  366           if (m == null)
  367               m = createJDBC3Method(SET_SAVEPOINT_NONAME, "setSavepoint", null);
  368           return (Savepoint) invokeJDBC3(m, null);
  369       }
  370   
  371       public Savepoint setSavepoint(String savepoint) throws SQLException {
  372           assertJDBC3();
  373           Method m = (Method) _jdbc3.get(SET_SAVEPOINT);
  374           if (m == null)
  375               m = createJDBC3Method(SET_SAVEPOINT, "setSavepoint",
  376                   new Class[]{ String.class });
  377           return (Savepoint) invokeJDBC3(m, new Object[]{ savepoint });
  378       }
  379   
  380       public void rollback(Savepoint savepoint) throws SQLException {
  381           assertJDBC3();
  382           Method m = (Method) _jdbc3.get(ROLLBACK_SAVEPOINT);
  383           if (m == null)
  384               m = createJDBC3Method(ROLLBACK_SAVEPOINT, "rollback",
  385                   new Class[]{ Savepoint.class });
  386           invokeJDBC3(m, new Object[]{ savepoint });
  387       }
  388   
  389       public void releaseSavepoint(Savepoint savepoint) throws SQLException {
  390           assertJDBC3();
  391           Method m = (Method) _jdbc3.get(RELEASE_SAVEPOINT);
  392           if (m == null)
  393               m = createJDBC3Method(RELEASE_SAVEPOINT, "releaseSavepoint",
  394                   new Class[]{ Savepoint.class });
  395           invokeJDBC3(m, new Object[]{ savepoint });
  396       }
  397   
  398       public Statement createStatement(int resultSetType,
  399           int resultSetConcurrency, int resultSetHoldability)
  400           throws SQLException {
  401           assertJDBC3();
  402           return createStatement(resultSetType, resultSetConcurrency,
  403               resultSetHoldability, true);
  404       }
  405   
  406       protected Statement createStatement(int resultSetType,
  407           int resultSetConcurrency, int resultSetHoldability, boolean wrap)
  408           throws SQLException {
  409           Statement stmnt;
  410           if (_del != null)
  411               stmnt = _del.createStatement(resultSetType, resultSetConcurrency,
  412                   resultSetHoldability, false);
  413           else {
  414               Method m = (Method) _jdbc3.get(CREATE_STATEMENT);
  415               if (m == null)
  416                   m = createJDBC3Method(CREATE_STATEMENT, "createStatement",
  417                       new Class[]{ int.class, int.class, int.class });
  418               stmnt = (Statement) invokeJDBC3(m, new Object[]{
  419                   Numbers.valueOf(resultSetType),
  420                   Numbers.valueOf(resultSetConcurrency),
  421                   Numbers.valueOf(resultSetHoldability) });
  422           }
  423           if (wrap)
  424               stmnt = new DelegatingStatement(stmnt, this);
  425           return stmnt;
  426       }
  427   
  428       public PreparedStatement prepareStatement(String sql,
  429           int resultSetType, int resultSetConcurrency, int resultSetHoldability)
  430           throws SQLException {
  431           assertJDBC3();
  432           return prepareStatement(sql, resultSetType, resultSetConcurrency,
  433               resultSetHoldability, true);
  434       }
  435   
  436       protected PreparedStatement prepareStatement(String sql,
  437           int resultSetType, int resultSetConcurrency, int resultSetHoldability,
  438           boolean wrap) throws SQLException {
  439           PreparedStatement stmnt;
  440           if (_del != null)
  441               stmnt = _del.prepareStatement(sql, resultSetType,
  442                   resultSetConcurrency, resultSetHoldability, false);
  443           else {
  444               Method m = (Method) _jdbc3.get(PREPARE_STATEMENT);
  445               if (m == null)
  446                   m = createJDBC3Method(PREPARE_STATEMENT, "prepareStatement",
  447                       new Class[]{ String.class, int.class, int.class,
  448                           int.class });
  449               stmnt = (PreparedStatement) invokeJDBC3(m, new Object[]{ sql,
  450                   Numbers.valueOf(resultSetType),
  451                   Numbers.valueOf(resultSetConcurrency),
  452                   Numbers.valueOf(resultSetHoldability) });
  453           }
  454           if (wrap)
  455               stmnt = new DelegatingPreparedStatement(stmnt, this);
  456           return stmnt;
  457       }
  458   
  459       public CallableStatement prepareCall(String sql,
  460           int resultSetType, int resultSetConcurrency, int resultSetHoldability)
  461           throws SQLException {
  462           assertJDBC3();
  463           return prepareCall(sql, resultSetType, resultSetConcurrency,
  464               resultSetHoldability, true);
  465       }
  466   
  467       protected CallableStatement prepareCall(String sql, int resultSetType,
  468           int resultSetConcurrency, int resultSetHoldability, boolean wrap)
  469           throws SQLException {
  470           CallableStatement stmnt;
  471           if (_del != null)
  472               stmnt = _del.prepareCall(sql, resultSetType,
  473                   resultSetConcurrency, resultSetHoldability, false);
  474           else {
  475               Method m = (Method) _jdbc3.get(PREPARE_CALL);
  476               if (m == null)
  477                   m = createJDBC3Method(PREPARE_CALL, "prepareCall",
  478                       new Class[]{ String.class, int.class, int.class,
  479                           int.class });
  480               stmnt = (CallableStatement) invokeJDBC3(m, new Object[]{ sql,
  481                   Numbers.valueOf(resultSetType),
  482                   Numbers.valueOf(resultSetConcurrency),
  483                   Numbers.valueOf(resultSetHoldability) });
  484           }
  485           if (wrap)
  486               stmnt = new DelegatingCallableStatement(stmnt, this);
  487           return stmnt;
  488       }
  489   
  490       public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
  491           throws SQLException {
  492           assertJDBC3();
  493           return prepareStatement(sql, autoGeneratedKeys, true);
  494       }
  495   
  496       protected PreparedStatement prepareStatement(String sql,
  497           int autoGeneratedKeys, boolean wrap) throws SQLException {
  498           PreparedStatement stmnt;
  499           if (_del != null)
  500               stmnt = _del.prepareStatement(sql, autoGeneratedKeys);
  501           else {
  502               Method m = (Method) _jdbc3.get(PREPARE_WITH_KEYS);
  503               if (m == null)
  504                   m = createJDBC3Method(PREPARE_WITH_KEYS, "prepareStatement",
  505                       new Class[]{ String.class, int.class });
  506               stmnt = (PreparedStatement) invokeJDBC3(m, new Object[]{ sql,
  507                   Numbers.valueOf(autoGeneratedKeys) });
  508           }
  509           if (wrap)
  510               stmnt = new DelegatingPreparedStatement(stmnt, this);
  511           return stmnt;
  512       }
  513   
  514       public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
  515           throws SQLException {
  516           assertJDBC3();
  517           return prepareStatement(sql, columnIndexes, true);
  518       }
  519   
  520       protected PreparedStatement prepareStatement(String sql,
  521           int[] columnIndexes, boolean wrap) throws SQLException {
  522           PreparedStatement stmnt;
  523           if (_del != null)
  524               stmnt = _del.prepareStatement(sql, columnIndexes, wrap);
  525           else {
  526               Method m = (Method) _jdbc3.get(PREPARE_WITH_INDEX);
  527               if (m == null)
  528                   m = createJDBC3Method(PREPARE_WITH_INDEX, "prepareStatement",
  529                       new Class[]{ String.class, int[].class });
  530               stmnt = (PreparedStatement) invokeJDBC3(m, new Object[]{ sql,
  531                   columnIndexes });
  532           }
  533           if (wrap)
  534               stmnt = new DelegatingPreparedStatement(stmnt, this);
  535           return stmnt;
  536       }
  537   
  538       public PreparedStatement prepareStatement(String sql, String[] columnNames)
  539           throws SQLException {
  540           assertJDBC3();
  541           return prepareStatement(sql, columnNames, true);
  542       }
  543   
  544       protected PreparedStatement prepareStatement(String sql,
  545           String[] columnNames, boolean wrap) throws SQLException {
  546           assertJDBC3();
  547           PreparedStatement stmnt;
  548           if (_del != null)
  549               stmnt = _del.prepareStatement(sql, columnNames, wrap);
  550           else {
  551               Method m = (Method) _jdbc3.get(PREPARE_WITH_NAMES);
  552               if (m == null)
  553                   m = createJDBC3Method(PREPARE_WITH_NAMES, "prepareStatement",
  554                       new Class[]{ String.class, String[].class });
  555               stmnt = (PreparedStatement) invokeJDBC3(m, new Object[]{ sql,
  556                   columnNames });
  557           }
  558           if (wrap)
  559               stmnt = new DelegatingPreparedStatement(stmnt, this);
  560           return stmnt;
  561       }
  562   
  563       private static void assertJDBC3() {
  564           if (_jdbc3 == null)
  565               throw new UnsupportedOperationException(_loc.get("not-jdbc3")
  566                   .getMessage());
  567       }
  568   
  569       private Object invokeJDBC3(Method m, Object[] args) throws SQLException {
  570           try {
  571               return m.invoke(_conn, args);
  572           } catch (Throwable t) {
  573               if (t instanceof SQLException)
  574                   throw(SQLException) t;
  575               throw new NestableRuntimeException(_loc.get("invoke-jdbc3")
  576                   .getMessage(), t);
  577           }
  578       }
  579   
  580       private static Method createJDBC3Method(Object key, String name,
  581           Class[] args) {
  582           try {
  583               Method m = Connection.class.getMethod(name, args);
  584               _jdbc3.put(key, m);
  585               return m;
  586           } catch (Throwable t) {
  587               throw new NestableRuntimeException(_loc.get("error-jdbc3")
  588                   .getMessage(), t);
  589           }
  590       }
  591   }

Save This Page
Home » apache-openjpa-1.1.0-source » org.apache.openjpa.lib » jdbc » [javadoc | source]