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).warn(e.getLocalizedMessage(), e);
99  								}
100 							}
101 						}
102 						finally
103 						{
104 							connectionManager.onAfterReleaseConnection((Connection) proxy);
105 							connection = null;
106 						}
107 						return null;
108 					}
109 					else if ("getConnection".equals(method.getName())) // NON-NLS
110 					{
111 						return connection;
112 					}
113 
114 					if (connection == null)
115 					{
116 						connection = connectionManager.getDataSource().getConnection();
117 
118 						// if we have a configuration, we have to replay it now
119 						Iterator iterConfiguration = connectionConfiguration.entrySet().iterator();
120 						while (iterConfiguration.hasNext())
121 						{
122 							Map.Entry config = (Map.Entry) iterConfiguration.next();
123 							((Method) config.getKey()).invoke(connection, (Object[]) config.getValue());
124 						}
125 
126 						connectionManager.onAfterBorrowConnection((Connection) proxy);
127 					}
128 
129 					Object ret = method.invoke(connection, args);
130 
131 					// capture the connection configuration
132 					if (method.getName().startsWith("set")) // NON-NLS
133 					{
134 						connectionConfiguration.put(method, args);
135 					}
136 
137 					return ret;
138 				}
139 			});
140 	}
141 }