View Javadoc

    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.myfaces.orchestra.connectionManager;
    20
    21  import org.apache.commons.logging.LogFactory;
    22
    23  import java.lang.reflect.InvocationHandler;
    24  import java.lang.reflect.Method;
    25  import java.lang.reflect.Proxy;
    26  import java.sql.Connection;
    27  import java.sql.SQLException;
    28  import java.util.HashMap;
    29  import java.util.Iterator;
    30  import java.util.Map;
    31
    32  /**
    33   * Create proxy connections able to handle disconnection of the underlying real connection.
    34   *
    35   * @see org.apache.myfaces.orchestra.connectionManager.DisconnectableConnection
    36   */
    37  public class DisconnectableConnectionFactory
    38  {
    39      private DisconnectableConnectionFactory()
    40      {
    41      }
    42
    43      public static DisconnectableConnection create(final ConnectionManagerDataSource connectionManager)
    44      {
    45          return (DisconnectableConnection) Proxy.newProxyInstance(
    46
    47              DisconnectableConnection.class.getClassLoader(),
    48
    49              new Class[]
    50                  {
    51                      DisconnectableConnection.class
    52                  },
    53
    54              new InvocationHandler()
    55              {
    56                  private Map connectionConfiguration = new HashMap();
    57                  private Connection connection;
    58
    59                  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    60                  {
    61                      if ("equals".equals(method.getName()) || "hashCode".equals(method.getName())) // NON-NLS
    62                      {
    63                          // do not pass these methods to the connection as we dont want to change the
    64                          // identity of the connection proxy
    65                          return method.invoke(this, args);
    66                      }
    67                      else if ("close".equals(method.getName())) // NON-NLS
    68                      {
    69                          try
    70                          {
    71                              if (connection != null)
    72                              {
    73                                  connection.close();
    74                              }
    75                              connection = null;
    76                          }
    77                          finally
    78                          {
    79                              connectionManager.onAfterReleaseConnection((Connection) proxy);
    80                          }
    81                          return null;
    82                      }
    83                      else if ("disconnect".equals(method.getName())) // NON-NLS
    84                      {
    85                          try
    86                          {
    87                              if (connection != null)
    88                              {
    89                                  try
    90                                  {
    91                                      if (!connection.isClosed())
    92                                      {
    93                                          connection.close();
    94                                      }
    95                                  }
    96                                  catch (SQLException e)
    97                                  {
    98                                      LogFactory.getLog(DisconnectableConnectionFactory.class)
    99                                          .warn(e.getLocalizedMessage(), e);
    100                                 }
    101                             }
    102                         }
    103                         finally
    104                         {
    105                             connectionManager.onAfterReleaseConnection((Connection) proxy);
    106                             connection = null;
    107                         }
    108                         return null;
    109                     }
    110                     else if ("getConnection".equals(method.getName())) // NON-NLS
    111                     {
    112                         return connection;
    113                     }
    114
    115                     if (connection == null)
    116                     {
    117                         connection = connectionManager.getDataSource().getConnection();
    118
    119                         // if we have a configuration, we have to replay it now
    120                         Iterator iterConfiguration = connectionConfiguration.entrySet().iterator();
    121                         while (iterConfiguration.hasNext())
    122                         {
    123                             Map.Entry config = (Map.Entry) iterConfiguration.next();
    124                             ((Method) config.getKey()).invoke(connection, (Object[]) config.getValue());
    125                         }
    126
    127                         connectionManager.onAfterBorrowConnection((Connection) proxy);
    128                     }
    129
    130                     Object ret = method.invoke(connection, args);
    131
    132                     // capture the connection configuration
    133                     if (method.getName().startsWith("set")) // NON-NLS
    134                     {
    135                         connectionConfiguration.put(method, args);
    136                     }
    137
    138                     return ret;
    139                 }
    140             });
    141     }
    142 }