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 }