Coverage Report - org.apache.ojb.broker.util.batch.PreparedStatementInvocationHandler
 
Classes in this File Line Coverage Branch Coverage Complexity
PreparedStatementInvocationHandler
N/A
N/A
10
 
 1  
 package org.apache.ojb.broker.util.batch;
 2  
 
 3  
 /* Copyright 2002-2005 The Apache Software Foundation
 4  
  *
 5  
  * Licensed under the Apache License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 
 19  
 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
 20  
 import org.apache.ojb.broker.platforms.PlatformFactory;
 21  
 import org.apache.ojb.broker.platforms.PlatformException;
 22  
 import org.apache.ojb.broker.platforms.Platform;
 23  
 
 24  
 import java.lang.reflect.Method;
 25  
 import java.lang.reflect.InvocationTargetException;
 26  
 import java.math.BigDecimal;
 27  
 import java.sql.Connection;
 28  
 import java.sql.PreparedStatement;
 29  
 import java.sql.SQLException;
 30  
 import java.util.ArrayList;
 31  
 
 32  
 //#ifdef JDK13
 33  
 import java.lang.reflect.InvocationHandler;
 34  
 //#else
 35  
 /*
 36  
 import com.develop.java.lang.reflect.InvocationHandler;
 37  
 */
 38  
 //#endif
 39  
 
 40  
 /**
 41  
  * The implementation of {@link java.reflect.InvocationHandler} which is used
 42  
  * to create dynamic proxy which will implement {@link java.sql.PreparedStatement} and
 43  
  * {@link BatchPreparedStatement}.
 44  
  *
 45  
  * @author Oleg Nitz (<a href="mailto:olegnitz@apache.org">olegnitz@apache.org</a>)
 46  
  */
 47  
 public class PreparedStatementInvocationHandler implements InvocationHandler
 48  
 {
 49  
 
 50  
     private final static Integer ONE = new Integer(1);
 51  
 
 52  
     private static Method ADD_BATCH;
 53  
 
 54  
     private final static Method SET_BIG_DECIMAL;
 55  
 
 56  
     static
 57  
     {
 58  
         Method setBigDecimal = null;
 59  
         try
 60  
         {
 61  
             setBigDecimal = PreparedStatement.class.getMethod("setBigDecimal",
 62  
                                                               new Class[] {Integer.TYPE, BigDecimal.class});
 63  
         }
 64  
         catch ( Exception ex )
 65  
         {
 66  
             // ignore it
 67  
         }
 68  
         SET_BIG_DECIMAL = setBigDecimal;
 69  
     }
 70  
 
 71  
     private final BatchConnection _batchConn;
 72  
 
 73  
     private final String _sql;
 74  
 
 75  
     private ArrayList _methods = new ArrayList();
 76  
 
 77  
     private ArrayList _params = new ArrayList();
 78  
 
 79  
     private Platform m_platform = null;
 80  
 
 81  
     public PreparedStatementInvocationHandler(BatchConnection batchConn, String sql, JdbcConnectionDescriptor jcd)
 82  
     {
 83  
         _batchConn = batchConn;
 84  
         _sql = sql;
 85  
         m_platform = PlatformFactory.getPlatformFor(jcd);
 86  
         try
 87  
         {
 88  
             ADD_BATCH = m_platform.getClass().getMethod("addBatch",new Class[]{PreparedStatement.class});
 89  
         }
 90  
         catch ( NoSuchMethodException e )
 91  
         {
 92  
             /**
 93  
              * should never happen
 94  
              */
 95  
             ADD_BATCH = null;
 96  
         }
 97  
         catch ( SecurityException e )
 98  
         {
 99  
             // ignore it
 100  
         }
 101  
     }
 102  
 
 103  
     public Object invoke(Object proxy, Method method, Object[] args)
 104  
     throws Throwable
 105  
     {
 106  
         String name = method.getName();
 107  
         if ( name.equals("executeUpdate") )
 108  
         {
 109  
             _methods.add(ADD_BATCH);
 110  
             _params.add(null);
 111  
             _batchConn.nextExecuted(_sql);
 112  
             return ONE;
 113  
         }
 114  
         else if ( name.equals("doExecute") )
 115  
         {
 116  
             doExecute((Connection) args[0]);
 117  
         }
 118  
         else if ( name.startsWith("set") )
 119  
         {
 120  
             // workaround for the bug in Sybase jConnect JDBC driver
 121  
             if ( name.equals("setLong") )
 122  
             {
 123  
                 method = SET_BIG_DECIMAL;
 124  
                 args[1] = BigDecimal.valueOf(((Long) args[1]).longValue());
 125  
             }
 126  
             _methods.add(method);
 127  
             _params.add(args);
 128  
         }
 129  
         return null;
 130  
     }
 131  
 
 132  
     /**
 133  
      * This method performs database modification at the very and of transaction.
 134  
      */
 135  
     private void doExecute(Connection conn) throws SQLException
 136  
     {
 137  
         PreparedStatement stmt;
 138  
         int size;
 139  
 
 140  
         size = _methods.size();
 141  
         if ( size == 0 )
 142  
         {
 143  
             return;
 144  
         }
 145  
         stmt = conn.prepareStatement(_sql);
 146  
         try
 147  
         {
 148  
             m_platform.afterStatementCreate(stmt);
 149  
         }
 150  
         catch ( PlatformException e )
 151  
         {
 152  
             if ( e.getCause() instanceof SQLException )
 153  
             {
 154  
                 throw (SQLException)e.getCause();
 155  
             }
 156  
             else
 157  
             {
 158  
                 throw new SQLException(e.getMessage());
 159  
             }
 160  
         }
 161  
         try
 162  
         {
 163  
             m_platform.beforeBatch(stmt);
 164  
         }
 165  
         catch ( PlatformException e )
 166  
         {
 167  
             if ( e.getCause() instanceof SQLException )
 168  
             {
 169  
                 throw (SQLException)e.getCause();
 170  
             }
 171  
             else
 172  
             {
 173  
                 throw new SQLException(e.getMessage());
 174  
             }
 175  
         }
 176  
         try
 177  
         {
 178  
             for ( int i = 0; i < size; i++ )
 179  
             {
 180  
                 Method method = (Method) _methods.get(i);
 181  
                 try
 182  
                 {
 183  
                     if ( method.equals(ADD_BATCH) )
 184  
                     {
 185  
                         /**
 186  
                          * we invoke on the platform and pass the stmt as an arg.
 187  
                          */
 188  
                         m_platform.addBatch(stmt);
 189  
                     }
 190  
                     else
 191  
                     {
 192  
                         method.invoke(stmt, (Object[]) _params.get(i));
 193  
                     }
 194  
                 }
 195  
                 catch (IllegalArgumentException ex)
 196  
                 {
 197  
                                         StringBuffer buffer = generateExceptionMessage(i, stmt, ex);
 198  
                                         throw new SQLException(buffer.toString());
 199  
                 }
 200  
                 catch ( IllegalAccessException ex )
 201  
                 {
 202  
                                         StringBuffer buffer = generateExceptionMessage(i, stmt, ex);
 203  
                     throw new SQLException(buffer.toString());
 204  
                 }
 205  
                 catch ( InvocationTargetException ex )
 206  
                 {
 207  
                     Throwable th = ex.getTargetException();
 208  
 
 209  
                     if ( th == null )
 210  
                     {
 211  
                         th = ex;
 212  
                     }
 213  
                     if ( th instanceof SQLException )
 214  
                     {
 215  
                         throw ((SQLException) th);
 216  
                     }
 217  
                     else
 218  
                     {
 219  
                         throw new SQLException(th.toString());
 220  
                     }
 221  
                 }
 222  
                                 catch (PlatformException e)
 223  
                                 {
 224  
                                         throw new SQLException(e.toString());
 225  
                                 }
 226  
             }
 227  
             try
 228  
             {
 229  
                 /**
 230  
                  * this will call the platform specific call
 231  
                  */
 232  
                 m_platform.executeBatch(stmt);
 233  
             }
 234  
             catch ( PlatformException e )
 235  
             {
 236  
                 if ( e.getCause() instanceof SQLException )
 237  
                 {
 238  
                     throw (SQLException)e.getCause();
 239  
                 }
 240  
                 else
 241  
                 {
 242  
                     throw new SQLException(e.getMessage());
 243  
                 }
 244  
             }
 245  
 
 246  
         }
 247  
         finally
 248  
         {
 249  
             stmt.close();
 250  
             _methods.clear();
 251  
             _params.clear();
 252  
         }
 253  
     }
 254  
     
 255  
     private StringBuffer generateExceptionMessage(int i, PreparedStatement stmt, Exception ex)
 256  
         {
 257  
                 StringBuffer buffer = new StringBuffer();
 258  
                 buffer.append("Method of type: ");
 259  
                 buffer.append(_methods.get(i));
 260  
                 buffer.append(" invoking on instance: ");
 261  
                 if (( _methods.get(i)).equals(ADD_BATCH))
 262  
                         buffer.append(m_platform);
 263  
                 else
 264  
                         buffer.append(stmt);
 265  
                 buffer.append(" with parameters: ");
 266  
                 if ((_methods.get(i)).equals(ADD_BATCH))
 267  
                         buffer.append(stmt);
 268  
                 else
 269  
                         buffer.append(_params.get(i));
 270  
                 buffer.append(" with root: ");
 271  
                 buffer.append(ex.toString());
 272  
                 return buffer;
 273  
         }
 274  
 }
 275